by andrew

Design patterns: factory

Next chapter in the book is quite long but it presents actually two design patterns: factory method and abstract factory. Both are explained to the reader in the same context: you are an owner of successful pizza shop. At the beginning the code of an application which helps you with your pizza shop is really simple:

But your clients expect from you to add more different kinds of pizza and this simple piece of code becomes bigger and bigger. Later you will probably have to remove some types of pizza because they will not sell well. The application code clearly is not closed for such modification. And when it got really big it will be easy to introduce bugs. As learnt earlier in the book we should encapsulate parts which changes. At this point in the book simple factory “pattern” is presented. It is not a real pattern but it is a warm-up before the factory method is described.

And this moment comes when you are informed that your pizza shop is doing so well that you have trounced the competition and are going to franchise your PizzaStore. And here comes first issue: there are different types of pizza depending on geographical region. Our pepperoni pizza in New York will have different crust and cheese than pepperoni pizza in Italy. First approach is to create different SimpleFactory subclasses which we pass as a parameter to PizzaStore constructor. So, the simple code would look like:

But we’d like to have more control to make sure nothing but pizza type changes in whole pizza-making process. You decide to change PizzaStore to an abstract class with abstract method createPizza. PizzaStore::createPizza() returns Pizza object which in our case can be an instance of NewYorkPizzaStore or ChicagoPizzaStore subclasses. The whole logic which was above deciding what Pizza instance should be returned depending on $type is now in new factory methods: NewYorkPizzaStore::createPizza() or ChicagoPizzaStore::createPizza() in example:

The Factory Method define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantion to the subclasses.

In terms of factory method we usually mention creator classes and product classes. In the example from our book the creators are all subclasses of PizzaStore (ie. NewYorkPizzaStore) classes and products are different classes which extends from Pizza base class.

Factory method helps our with sticking to another design principle: Dependency Inversion Principle. Without our factory method our PizzaStore was closely connected to all *Pizza classes (ie. NewYorkStyleCheesePizza). PizzaStore was depended on other pizza types. If we had changed anything in PizzaStore we did have to change all classes it was depended on. With implementation of abstract Pizza class PizzaStore is now depended only on Pizza.

After contemplation about DIP we got back to our pizza store. It occurs (how surprisingly!) that in different regions not only pizza crust is different. The pizza ingredients differs as well! So, the cheese in New York is different than cheese in Chicago. Surely in near future we’ll have another group of regionally different ingredients. What happens next? We’re lead step by step with building PizzaIngredientFactory (the base interface and its regional subclasses), we implement changes in Pizza class and finally changes in PizzaStore. After those changes the flow looks like:

Application creates an instance of PizzaStore:

$newYorkPizzaStore = new NewYorkPizzaStore();

It takes the order:

$newYorkPizzaStore->orderPizza("cheese");

The PizzaStore::orderPizza() method calls PizzaStore::createPizza():

$pizza = $this->createPizza("cheese");

Here the ingredient factory is being used:

$pizza = new CheesePizza($this->newYorkIngredientsFactory);

Next step is to prepare the pizza. Once it’s called, the factory method is asked to prepare ingredients:

Finally, we have the prepared pizza in hand and the PizzaStore::orderPizza() method bakes, cuts and boxes the pizza.

And at this point we’re introduced to:

The Abstract Factory Pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes.

And it’s quite complicated diagram:

Abstract factory pattern diagram from Head First: Design Patterns

At the end of this chapter we are presented with really nice comparison of these two new patterns: Factory Method and Abstract Factory. We’re explained that their are really similar but shouldn’t be lump in with each other. We should use Abstract Factory whenever we have families of products we need to create and we want to make sure our clients create products that belong together. And we should use Factory Method to decouple our client code from concrete classes we need to instantiate, or if we don’t know ahead of time all the concrete classes we are going to need.

Other examples

Since the factory patterns creates instances of objects there are lots of examples on the Internet. Most of the first results in Google I get are rather hypothetical problems. Mostly those are results of pages where authors try to teach readers about the patterns. But one of them is really close to reality. It’s about creating images with factory method pattern.