Consider now that the Client changes her requirements. She previously wanted us to make a software for a Pepsi Fountain machine that serves Pepsi, 7UP and Mirinda. She now also wants a Coke Fountain to serve Cocacola, Sprite and Fanta.
The requirement is only a small overhead, but if we want to keep the Simple Factory we created previously we need to do a whole bunch of copy-paste and minor modifications here and there.
This seems to be a fairly good solution, but the two fountain classes are doing almost the same thing, except
during the initialization of the drinks. We educate ourselves with another important suggestion of using design patterns:
"Depend on Abstractions, not on Concretions"
Notice how we have introduced a level of abstraction into our Fountains. We can use the AbstractFountain
reference for the two distinct fountains and initialize the reference with the PepsiFountain or CocacolaFountain as required in our program. Also notice how the common algorithm of getting a drink remains in the AbstractFountain while we have created the abstract method createDrink() inside our abstract class whose responsibility is to create the Drink. This method behaves like a factory and is aptly called the 'Factory Method'. We have indeed used the Factory method pattern here. The AbstractFountain is using its subclasses to specify which objects it creates and hence has no knowledge of which particular drink is being created. This knowledge of which drink is being created is localized at the concrete Fountain implementations namely PepsiFountain and CocacolaFountain.
More formally we may define the Factory Method as follows:
The Factory Method provides a simple decision making class that returns one of several possible subclasses of an abstract base class depending on the data that are provided.