Chapter 4 in the
Head First Design Patterns book explains Factory Method design pattern. As we learned in previous posts to "encapsulate what varies", we can apply same technique to "encapsulate the code that create objects". When you have code that create objects or instantiates concrete classes, then it can be an area of frequent change.
We create objects by using new operator but there is more to making objects than just using new operator. As per design principle 2 we should "Program to an interface, not an implementation". Why ? Because if code is written to an interface, then it will work with any new classes implementing that interface through polymorphism. When I say interface here then in C++ there is no clear distinction between interface and abstract class, unlike in C# and Java. To get a fair idea of interfaces and abstract classes in C++, you can refer stackoverflow discussions
here and
here. Generally speaking
interface can also refer to a function's signature.
Whenever you see "new", think "concrete". When you use "new" you are certainly instantiating a concrete class, so that's an implementation and not an interface. When you have a code that makes use of lots of concrete classes then it will be prone to bugs because code may have to be changed as new concrete classes are added. So code will not be "closed for modifications" and hence violate our design principle 4 discussed in last post.
Anywhere in a code if you use "new", you'll be holding a reference to a concrete class, you should be using a Factory method to get around that! Factory method can be defined as
" The Factory Method Pattern defines an interface for creating an object, but lets subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses."
The 'interface' above is factory 'method'. A factory method handles object creation and encapsulates it in a subclass. This decouples the client code in the superclass from the object creation code in the subclass. A factory method looks like
abstract Product factoryMethod(String type)
A factory method returns a Product that is typically used within methods defined in the superclass. Client is actually code in superclass, factoryMethod isolates the client code from knowing what kind of concrete Product is actually created.
In the example code the PizzaStore class is the Creator class that contains the implementations for all of the methods to manipulate products, except for the factory method. The abstract factoryMethod ( createPizza(string) ) is what all Creater subclasses must implement ( ChicagoPizzaStore, NYPizzaStore ). The Concrete Creater( ChicagoPizzaStore, NYPizzaStore ) implements the factoryMethod(), which is the method that actually produce Products.
Pizza is the Product and all concrete products ( NYStyleCheesePizza, ChicagoStyleCheesePizza ... ) must implement the same interface so that the classes which use the products can refer to the interface not the Concrete Product ( NYStyleCheesePizza, ChicagoStyleCheesePizza etc. ).
Here is the class diagram of PizzaStore
The c++ code is build using VS2010 IDE. You can download code from
here.