I am reading the book »Head First Design Patterns« from O'Reilly. Before explaining the Factory Method Pattern, they introduce a Simple Factory first.
They are using the example of a pizzeria. In a first step they show the problem:
Pizza orderPizza(string type) {
Pizza pizza;
if (type.equals("Pepperoni") { pizza = new PepperoniPizza(); }
else if (type.equals("Salmon") { pizza = new SalmonPizza(); }
// ... and so on
pizza.Prepare();
pizza.Bake();
pizza.Cut();
pizza.Pack();
return pizza;
}
The obvious problem is that you had to change Pizzeria whenever you add or remove a Pizza.
Hence they introduce a "Simple Factory Idiom" first. They move the creating part into a class "SimplePizzaFactory". Now you don't need to modify Pizzeria anymore when adding or removing a Pizza.
Then they say that this approach isn't that good, when you have more than one pizzeria (in several towns).
I don't really understand their reasoning. They give the following example code and then they say that each pizzeria wouldn't be using the procedure as implemented above but were using different methods in order to "bake", "cut" and "pack" the pizza.
BerlinPizzaFactory berlinFactory = new BerlinPizzaFactory();
Pizzeria berlinPizzeria = new Pizzeria(berlinFactory);
berlinPizza.Order("Pepperoni");
Instead of using the Simple Factory, they suggest using the Factory Method Pattern.
First, I don't see why the BerlinPizzeria is supposed to not using the procedure. It's still a Pizzeria and when you call Order, you're using the same procedure.
My best guess is that they are implying that you are able to implement, let's say, a cafeteria (I'm deliberately using something entirely different to make my point) and use the factory (as it is independent of the pizzeria) and prepare the pizza in a way you want to.
But even when using the Factory Method Pattern, nobody forces you to use the default procedure. It's even simpler to "hide" that you're doing it differently. Their code examples are given in Java and Java methods are virtual by default. So I would be able to implement BerlinPizzeria and override Order (or had to explicitly declare the method as final). The client, however, wouldn't notice that my BerlinPizzeria is doing things differently.
In conclusion I don't see any significant difference between a Simple Factory and the Factory Method Pattern. The only advantage of the Factory Method Pattern I'm seeing is that you would save a few classes (namely, the 'outsourced' factories).
So, what is really the disadvantages of a Simple Factory and why isn't is a good idea to 'outsource' the creating part?
Or what is really the advantage of the Factory Method pattern and why is it a good idea to force the creating part being implemented in the subclass?
Best Answer
Let's have a look at the
Simple Factory
The intention for theSimple Factory
is straightforward: It produces instances of concrete classes. Sticking to your example: you have aPizzeria
with methods likeorder()
:This is really a simple case of a factory. If you decide, that you wanted a Salmone-Pizza, you simply order an instance like this:
The advantage: you separated the use of Pizzas from its creation. You only want Pizza, independend of its creation process. You could enjoy Pizza without baking one yourself.
The downside: If you have several subtypes of the given flavours of Pizza (e.g. ROMANABerlinStyle, ROMANAHamburgStyle) you have two choices.
1) to add the new kind to the existing Pizzeria. That clutters your Pizzeria and you have to deal with several flavours, which aren't that different (e.g. ROMANABerlinStyle adds garlic and ROMANAHamburgStyle adds wild garlic) in one Pizzeria. Besides: it is of no advantage knowing, that you consume a berlinstyle or hamburgstyle pizza. You only wanted some well defined kind of Pizza from the Pizzeria.
2) you abstract one step further: you separate the individual flavours of the given kinds
QUADDROSTAGGIONI, SALMONE, ROMANA
into independend factories. That means, theBerlinPizzeria
knows its recipe and so does theHamburgPizzeria
.You are now allowed to have many different Pizzerias which could have their own recipes:
The traditional Pizzeria from above
and a berlinstyle one
Now you are able to start out your franchise:
If you are in Berlin you simply inject your
BerlinPizzeriaImpl
.The advantage: you are free to decide which flavour you support in each city (BerlinRomana, BerlinSalmone, traditional Quadrostaggioni). And this is completely transparent to your customer/consumer.
This follows the OpenClosed-principle: Your Pizzeria is closed, as you have a fixed set of pizzas, which you deliver (QUADDROSTAGGIONI, SALMONE, ROMANA), but you are open for new flavours, e.g. berlinstyle.
Further: each pizzeria itself is devoted to one style of pizza. The
BerlinPizzeriaImpl
doesn't care how to do a traditional Romana (Single Responsibilty Principle).Last but not least, you decouple different pizza styles from the franchise. The franchise needs only to know how to handle orders.
EDIT: I substituted the dead body with a delicious but dead fish :D