Design Patterns
- Factory Method
Factory Method - Define an interface for creating an object, but let subclasses decide which class to instantiate.
Factory Method lets a class defer instantiation to subclasses. To name the method more descriptively, it can be named as Factory and Product Method or Virtual Constructor. The Factory Method is closely related to Abstract Factory and Prototype patterns.
In Factory Method, client knows about abstract base class but not concrete subclass. Client wants to create an object from abstract class. But the subclass decides which class to instantiate. This allows us to defer the creation to the subclass. Again, the client doesn't know which subclass or concrete class is used to create the object. The creation is deferred to run-time.
- Client knows about abstract base class but not concrete subclass.
- Run-time creation of objects.
- Subclasses create objects.
Actually, the factory method is a way of circumventing following limitations of C++ constructor:
- No return type
A constructor cannot return a result, which means that we cannot signal an error during object initialization. The only way of doing it is to throw an exception from a constructor. - Naming
A constructor should have the same name as the class, which means we cannot have two constructors that both take a single argument. - Compile time bound
At the time when we create an object, we must specify the name of a concrete class which is known at compile time. There is no way of dynamic binding constructors at run time. - There is no virtual constructor
We cannot declare a virtual constructor. We should specify the exact type of the object at compile time, so that the compiler can allocate memory for that specific type. If we are constructing derived object, the compiler calls the base class constructor first, and the derived class hasn't been initialized yet. This is the reason why we cannot call virtual methods from the constructor.
In general, we can apply this pattern to the cases:
- When the client doesn't know the actual class from which subclass to create the object.
- When the client wants to delegate the decision of choosing the concrete class to create the object to one of the subclasses.
- When the client wants the subclass to specify the concrete class name from which to create an object.
If we want to create an OSX style button, we can write a code like this:
Button *btn = new OSXButton;But if we're going to make it work across any platform, we should write a code something similar to this:
Button *btn = guiFactory->createButton();Because guiFactory is an instance of Factory class, the createButton() returns a new instance of OSX style button after selecting appropriate button to create. The Factory itself is a subclass of GUIFactory which is an abstract class where general interface for widgets.
So, the product objects here, are widgets.
The instance variable guiFactory is initialized as:
GUIFactory *guiFactory = new Factory;
Diagram source: wiki
There are two major variations of the Factory Method pattern according to "Design Patterns" by Erich Gamma et al.:
- The case when the Creator class is an abstract class and does not provide an implementation for the factory method it declares.
This requires subclasses to define an implementation, because there's no reasonable default. It gets around the dilemma of having to instantiate unforeseeable classes. - The case when 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.
Here is the example code:
#include <iostream> class Button { public: virtual void paint() = 0; }; class OSXButton: public Button { public: void paint() { std::cout << "OSX button \n"; } }; class WindowsButton: public Button { public: void paint() { std::cout << "Windows button \n"; } }; class GUIFactory { public: virtual Button *createButton(char *) = 0; }; class Factory: public GUIFactory { public: Button *createButton(char *type) { if(strcmp(type,"Windows") == 0) { return new WindowsButton; } else if(strcmp(type,"OSX") == 0) { return new OSXButton; } } }; int main() { GUIFactory* guiFactory; Button *btn; guiFactory = new Factory; btn = guiFactory->createButton("OSX"); btn -> paint(); btn = guiFactory->createButton("Windows"); btn -> paint(); return 0; }
Output:
OSX button Windows button
We made two types of buttons without knowing their specific class names. We defer the instantiation to Factory class to create the two objects.
In essence, a factory method is a normal method which returns an instance of a class (in the example, it is an object of Button class).
In the example below, unlike the previous one, we use GUIFactory as a concrete class:
#include <iostream> class Button { public: virtual void paint() = 0; }; class OSXButton: public Button { public: void paint() { std::cout << "OSX button \n"; } }; class WindowsButton: public Button { public: void paint() { std::cout << "Windows button \n"; } }; class iPhoneButton: public Button { public: void paint() { std::cout << "iPhone button \n"; } }; class GUIFactory { public: virtual Button *createButton(char *type) { if(strcmp(type,"Windows") == 0) { return new WindowsButton; } else if(strcmp(type,"OSX") == 0) { return new OSXButton; } return NULL; } }; class Factory: public GUIFactory { Button *createButton(char *type) { if(strcmp(type,"Windows") == 0) { return new WindowsButton; } else if(strcmp(type,"OSX") == 0) { return new OSXButton; } else if(strcmp(type,"iPhone") == 0) { return new iPhoneButton; } } }; int main() { GUIFactory* guiFactory; Button *btn; guiFactory = new Factory; btn = guiFactory->createButton("OSX"); btn -> paint(); btn = guiFactory->createButton("Windows"); btn -> paint(); btn = guiFactory->createButton("iPhone"); btn -> paint(); return 0; }
Output:
OSX button Windows button iPhoneButton
What's the difference between Abstract Factory Pattern and Factory Method?
- Abstract Factory design pattern creates Factory
- Factory design pattern creates Products
Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization