Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.
Virtual Constructor
Frameworks use abstract classes to define and maintain relationships between objects. A framework is often responsible for creating these objects as well.
Consider a framework for applications that can present multiple documents to the user. Two key abstractions in this framework are the classes Application and Document. Both classes are abstract, and clients have to subclass them to realize their application-specific implementations. To create a drawing application, for example, we define the classes DrawingApplication and DrawingDocument. The Application class is responsible for managing Documents and will create them as requiredwhen the user selects Open or New from a menu, for example.
Because the particular Document subclass to instantiate is application-specific, the Application class can't predict the subclass of Document to instantiatethe Application class only knows when a new document should be created, not what kind of Document to create. This creates a dilemma: The framework must instantiate classes, but it only knows about abstract classes, which it cannot instantiate.
The Factory Method pattern offers a solution. It encapsulates the knowledge of which Document subclass to create and moves this knowledge out of the framework.
Application subclasses redefine an abstract CreateDocument operation on Application to return the appropriate Document subclass. Once an Application subclass is instantiated, it can then instantiate application-specific Documents without knowing their class. We call CreateDocument a factory method because it's responsible for "manufacturing" an object.
Use the Factory Method pattern when
Factory methods eliminate the need to bind application-specific classes into your code. The code only deals with the Product interface; therefore it can work with any user-defined ConcreteProduct classes.
A potential disadvantage of factory methods is that clients might have to subclass the Creator class just to create a particular ConcreteProduct object. Subclassing is fine when the client has to subclass the Creator class anyway, but otherwise the client now must deal with another point of evolution.
Here are two additional consequences of the Factory Method pattern:
In the Document example, the Document class could define a factory method called CreateFileDialog that creates a default file dialog object for opening an existing document. A Document subclass can define an application-specific file dialog by overriding this factory method. In this case the factory method is not abstract but provides a reasonable default implementation.
Parallel class hierarchies result when a class delegates some of its responsibilities to a separate class. Consider graphical figures that can be manipulated interactively; that is, they can be stretched, moved, or rotated using the mouse. Implementing such interactions isn't always easy. It often requires storing and updating information that records the state of the manipulation at a given time. This state is needed only during manipulation; therefore it needn't be kept in the figure object. Moreover, different figures behave differently when the user manipulates them. For example, stretching a line figure might have the effect of moving an endpoint, whereas stretching a text figure may change its line spacing.
With these constraints, it's better to use a separate Manipulator object that implements the interaction and keeps track of any manipulation-specific state that's needed. Different figures will use different Manipulator subclasses to handle particular interactions. The resulting Manipulator class hierarchy parallels (at least partially) the Figure class hierarchy:
The Figure class provides a CreateManipulator factory method that lets clients create a Figure's corresponding Manipulator. Figure subclasses override this method to return an instance of the Manipulator subclass that's right for them. Alternatively, the Figure class may implement CreateManipulator to return a default Manipulator instance, and Figure subclasses may simply inherit that default. The Figure classes that do so need no corresponding Manipulator subclasshence the hierarchies are only partially parallel.
Notice how the factory method defines the connection between the two class hierarchies. It localizes knowledge of which classes belong together.
Consider the following issues when applying the Factory Method pattern:
The first case requires subclasses to define an implementation, because there's no reasonable default. It gets around the dilemma of having to instantiate unforeseeable classes. In the second case, the concrete Creator uses the factory method primarily for flexibility. It's following a rule that says, "Create objects in a separate operation so that subclasses can override the way they're created." This rule ensures that designers of subclasses can change the class of objects their parent class instantiates if necessary.
The Unidraw graphical editing framework [VL90] uses
this approach for reconstructing objects saved on disk. Unidraw
defines a Creator
class with a factory method
Create
that takes a class identifier as an argument. The
class identifier specifies the class to instantiate. When Unidraw
saves an object to disk, it writes out the class identifier first and
then its instance variables. When it reconstructs the object from
disk, it reads the class identifier first.
Once the class identifier is read, the framework calls
Create
, passing the identifier as the parameter.
Create
looks up the constructor for the corresponding class
and uses it to instantiate the object. Last, Create
calls
the object's Read
operation, which reads the remaining
information on the disk and initializes the object's instance
variables.
A parameterized factory method has the following general form, where
MyProduct
and YourProduct
are subclasses of
Product
:
class Creator { public: virtual Product* Create(ProductId); }; Product* Creator::Create (ProductId id) { if (id == MINE) return new MyProduct; if (id == YOURS) return new YourProduct; // repeat for remaining products...return 0; }
Overriding a parameterized factory method lets you easily and selectively extend or change the products that a Creator produces. You can introduce new identifiers for new kinds of products, or you can associate existing identifiers with different products.
For example, a subclass MyCreator
could swap MyProduct and
YourProduct and support a new TheirProduct
subclass:
Product* MyCreator::Create (ProductId id) { if (id == YOURS) return new MyProduct; if (id == MINE) return new YourProduct; // N.B.: switched YOURS and MINE if (id == THEIRS) return new TheirProduct;return Creator::Create(id); // called if all others fail }
Notice that the last thing this operation does is call
Create
on the parent class. That's because
MyCreator::Create
handles only YOURS
,
MINE
, and THEIRS
differently than the parent
class. It isn't interested in other classes. Hence
MyCreator
extends the kinds of products created, and it
defers responsibility for creating all but a few products to its
parent.
Smalltalk programs often use a method that returns the class of the object to be instantiated. A Creator factory method can use this value to create a product, and a ConcreteCreator may store or even compute this value. The result is an even later binding for the type of ConcreteProduct to be instantiated.
A Smalltalk version of the Document example can define a
documentClass
method on Application
.
The documentClass
method returns the proper
Document
class for instantiating documents. The
implementation of
documentClass
in MyApplication
returns the
MyDocument
class. Thus in class
Application
we have
clientMethod document := self documentClass new. documentClass self subclassResponsibility
In class MyApplication
we have
documentClass ^ MyDocument
which returns the class MyDocument
to be instantiated to
Application
.
An even more flexible approach akin to parameterized factory methods
is to store the class to be created as a class variable of
Application
. That way you don't have to subclass
Application
to vary the product.
Factory methods in C++ are always virtual functions and are often pure virtual. Just be careful not to call factory methods in the Creator's constructorthe factory method in the ConcreteCreator won't be available yet.
You can avoid this by being careful to access products solely through accessor operations that create the product on demand. Instead of creating the concrete product in the constructor, the constructor merely initializes it to 0. The accessor returns the product. But first it checks to make sure the product exists, and if it doesn't, the accessor creates it. This technique is sometimes called lazy initialization. The following code shows a typical implementation:
class Creator { public: Product* GetProduct(); protected: virtual Product* CreateProduct(); private: Product* _product; }; Product* Creator::GetProduct () { if (_product == 0) { _product = CreateProduct(); } return _product; }
class Creator { public: virtual Product* CreateProduct() = 0; }; templateclass StandardCreator: public Creator { public: virtual Product* CreateProduct(); }; template Product* StandardCreator ::CreateProduct () { return new TheProduct; }
With this template, the client supplies just the product classno subclassing of Creator is required.
class MyProduct : public Product { public: MyProduct(); // ... }; StandardCreatormyCreator;
Class* DoMakeClass()
, where
Class
is the Product class.The function CreateMaze
(page 84) builds and returns a
maze. One problem with this function is that it hard-codes the
classes of maze, rooms, doors, and walls. We'll introduce factory
methods to let subclasses choose these components.
First we'll define factory methods in MazeGame
for
creating the maze, room, wall, and door objects:
class MazeGame { public: Maze* CreateMaze(); // factory methods: virtual Maze* MakeMaze() const { return new Maze; } virtual Room* MakeRoom(int n) const { return new Room(n); } virtual Wall* MakeWall() const { return new Wall; } virtual Door* MakeDoor(Room* r1, Room* r2) const { return new Door(r1, r2); } };
Each factory method returns a maze component of a given type.
MazeGame
provides default implementations that return the
simplest kinds of maze, rooms, walls, and doors.
Now we can rewrite CreateMaze
to use these factory methods:
Maze* MazeGame::CreateMaze () { Maze* aMaze = MakeMaze(); Room* r1 = MakeRoom(1); Room* r2 = MakeRoom(2); Door* theDoor = MakeDoor(r1, r2); aMaze->AddRoom(r1); aMaze->AddRoom(r2); r1->SetSide(North, MakeWall()); r1->SetSide(East, theDoor); r1->SetSide(South, MakeWall()); r1->SetSide(West, MakeWall()); r2->SetSide(North, MakeWall()); r2->SetSide(East, MakeWall()); r2->SetSide(South, MakeWall()); r2->SetSide(West, theDoor); return aMaze; }
Different games can subclass MazeGame
to specialize parts of
the maze. MazeGame
subclasses can redefine some or all of
the factory methods to specify variations in products. For example, a
BombedMazeGame
can redefine the Room
and
Wall
products to return the bombed varieties:
class BombedMazeGame : public MazeGame { public: BombedMazeGame(); virtual Wall* MakeWall() const { return new BombedWall; } virtual Room* MakeRoom(int n) const { return new RoomWithABomb(n); } };
An EnchantedMazeGame
variant might be defined like this:
class EnchantedMazeGame : public MazeGame { public: EnchantedMazeGame(); virtual Room* MakeRoom(int n) const { return new EnchantedRoom(n, CastSpell()); } virtual Door* MakeDoor(Room* r1, Room* r2) const { return new DoorNeedingSpell(r1, r2); } protected: Spell* CastSpell() const; };
Factory methods pervade toolkits and frameworks. The preceding document example is a typical use in MacApp and ET++ [WGM88]. The manipulator example is from Unidraw.
Class View in the Smalltalk-80 Model/View/Controller framework has a method defaultController that creates a controller, and this might appear to be a factory method [Par90]. But subclasses of View specify the class of their default controller by defining defaultControllerClass, which returns the class from which defaultController creates instances. So defaultControllerClass is the real factory method, that is, the method that subclasses should override.
A more esoteric example in Smalltalk-80 is the factory method parserClass defined by Behavior (a superclass of all objects representing classes). This enables a class to use a customized parser for its source code. For example, a client can define a class SQLParser to analyze the source code of a class with embedded SQL statements. The Behavior class implements parserClass to return the standard Smalltalk Parser class. A class that includes embedded SQL statements overrides this method (as a class method) and returns the SQLParser class.
The Orbix ORB system from IONA Technologies [ION94] uses
Factory Method to generate an appropriate type of proxy (see
Proxy (
Abstract Factory (87) is often implemented with factory methods. The Motivation example in the Abstract Factory pattern illustrates Factory Method as well.
Factory methods are usually called within Template Methods (325). In the document example above, NewDocument is a template method.
Prototypes (117) don't require subclassing Creator. However, they often require an Initialize operation on the Product class. Creator uses Initialize to initialize the object. Factory Method doesn't require such an operation.