This mechanism makes changing the entiry family of objects easy - because the specific class of factory object appears only once in the application - where it was instantiated. The application can replace the entire family of objects by simply instantiating a different instance of the abstract factory. It also provides for lazy creation of objects.
The participating actors here are the client, the abstract factory, the abstract product, the concrete factory and the concrete product. The abstract factory defines which objects the concrete factory will need to be able to create. The concrete factory must create the correct objects for its context, ensuring that all objects created by the concrete factory are able to work correctly for a given circumstance.
Lets take an example to explain the situation. The AbstractBookFactory specifies that two classes - the AbstractPHPBook and the AbstractMySQLBook will need to be created by the concrete factory. The concreate factory OReillyBookFactory extends the AbstractBookFactory and can create the objects for OReillyPHPBook and OReillyMySQLBook which are correct classes for the context of OReilly.
abstract class AbstractBookFactory { abstract function makePHPBook(); abstract function makeMySQLBook(); } //for objects in context of OReilly class OReillyBookFactory extends AbstractBookFactory { private $context = "OReilly"; function makePHPBook() { return new OReillyPHPBook; } function makeMySQLBook() { return new OReillyMySQLBook; } } //for objects in context of Sams class SamsBookFactory extends AbstractBookFactory { private $context = "Sams"; function makePHPBook() { return new SamsPHPBook; } function makeMySQLBook() { return new SamsMySQLBook; } } //Classes for books abstract class AbstractBook { abstract function getAuthor(); abstract function getTitle(); } abstract class AbstractPHPBook { private $subject = "PHP"; } abstract class AbstractMySQLBook { private $subject = "MySQL"; } class OReillyPHPBook extends AbstractPHPBook { private $author; private $title; function __construct() { $this->author = "OReilly : php author 1"; $this->title = "OReilly : title for php"; } function getAuthor() { return $this->author; } function getTitle() { return $this->title; } } class SamsPHPBook extends AbstractPHPBook { private $author; private $title; function __construct() { $this->author = "Sams : php author"; $this->title = "Sams : title for php"; } function getAuthor() { return $this->author; } function getTitle() { return $this->title; } } class OReillyMySQLBook extends AbstractMySQLBook { private $author; private $title; function __construct() { $this->author = "OReilly : MySQL author"; $this->title = "OReilly : title for MySQL"; } function getAuthor() { return $this->author; } function getTitle() { return $this->title; } } class SamsMySQLBook extends AbstractMySQLBook { private $author; private $title; function __construct() { $this->author = "Sams : MySQL author"; $this->title = "Sams : title for MySQL"; } function getAuthor() { return $this->author; } function getTitle() { return $this->title; } } //testing echo("Begin\n"); echo("Testing OReillyBookFactory\n"); $bookFactoryInstance = new OReillyBookFactory; testConcreteFactory($bookFactoryInstance); echo("----\n"); echo("Testing SamsBookFactory\n"); $bookFactoryInstance = new SamsBookFactory; testConcreteFactory($bookFactoryInstance); echo("----\n"); function testConcreteFactory($bookFactoryInstance) { $phpBook = $bookFactoryInstance->makePHPBook(); echo "php author : ".$phpBook->getAuthor()."\n"; echo "php title : ".$phpBook->getTitle()."\n"; $mysqlBook = $bookFactoryInstance->makeMySQLBook(); echo "mysql author : ".$mysqlBook->getAuthor()."\n"; echo "mysql title : ".$mysqlBook->getTitle()."\n"; } //Output Begin Testing OReillyBookFactory php author : OReilly : php author 1 php title : OReilly : title for php mysql author : OReilly : MySQL author mysql title : OReilly : title for MySQL ---- Testing SamsBookFactory php author : Sams : php author php title : Sams : title for php mysql author : Sams : MySQL author mysql title : Sams : title for MySQL ----
Another example using java
interface GUIFactory //Abstract Factory { public Button createButton(); } class WinFactory implements GUIFactory //concrete Factory { public Button createButton() { return new WinButton(); } } class OSXFactory implements GUIFactory //Concrete Factory { public Button createButton() { return new OSXButton(); } } interface Button //Abstract Product { public void paint(); } class WinButton implements Button //concrete Product { public void paint() { System.out.println("I'm a WinButton"); } } class OSXButton implements Button //concrete Product { public void paint() { System.out.println("I'm an OSXButton"); } } class Application //execution free of product type { public Application(GUIFactory factory) { Button button = factory.createButton(); button.paint(); } } public class ApplicationRunner { public static void main(String[] args) { if(args.length != 1) { System.out.println("usage : java ApplicationRunner <0/1>"); System.exit(1); } new Application(createOsSpecificFactory(args[0])); } public static GUIFactory createOsSpecificFactory(String ostype) { if (ostype.equals("0")) { return new WinFactory(); } else { return new OSXFactory(); } } } Output ------ $ java ApplicationRunner 0 I'm a WinButton $ java ApplicationRunner 1 I'm an OSXButton
No comments:
Post a Comment