I know there are a lot of questions out there about differences of different factory patterns, but the answers are so different and confusing. The books that i read use uncl
Here is a simple guideline I can think of following -
The basic differentiation between these two is one provides a concrete creator (Simple Factory) while the other(Factory method) supports decoupling of creator by inheritence so that multiple creators can be supported. An example to make it clearer -
Button
with different types - Toggle
, ImageButton
etc. Its more likely that you would have different creators of Button. For eg. based on different operating systems, WindowsButtonFactory, OSXButtonFactory
etc. Factory method is suitable in this case with an abstract class ButtonFactory
being implemented by WindowsButtonFactory, OSXButtonFactory
(and many more in future).Book
based on genre - Fiction, NonFiction
etc. More than often you would think a concrete Factory should be enough here.Simple Factory is a factory in the form of a class. Because of that it doesn't solve the problem with elegance, since for every new subclass of Product you will have to edit the switch statement in the create() method. This is a violation of the Open/Close Principle. A potential way to make a Simple Factory useful would be to use class registration as sawn here: http://www.oodesign.com/factory-pattern.html
Factory Method is a factory in the form of a method (hence the name). This doesn't violate the Open/Close Principle since you deal with change by extending and not by modifying code.
Your understanding is correct. Client and Creator/Factory in FMP are the same since the Factory (method) is part of the Client.
It is true that the create method in FMP is not reusable. That is ok though, because this is not an attempt to create an application-wide Factory of the Product, but a way for the Client to create his depended objects without using new.
I cannot answer you third question since I believe it is based on preference.
You are seeing examples of two styles of factory method because there are two completely separate situations where they are appropriate.
The first type - which seems to coincide with what you are being led to call a simple factory comes about when you have a relatively complicated object that can be difficult to create because of it's complexity.
The classic example here is the Pizza
class which has a PizzaConstructor
class (or some similar name) where much of the clevers required to build the Pizza
object is encoded into the Constructor
.
There's a nice discussion here but the salient point is that this form puts the clevers of how to construct the Pizza
in a Factory
rather than bogging down the Pizza
class.
With this technique you can make constructor code that is much clearer than it would normally be.
Pizza pizza = PizzaFactory.addTopping(Cheese)
.addTopping(Anchovies)
.thickCrust()
.stuffedCrust(Gruyere)
.stoneBaked()
.buildPizza();
The second situation for the use of factories is when you need your class to be able to actually make objects of a supplied type. This is difficult without the user supplying a factory mechanism for you to use. The user then supplies a factory mechanism of some sort, perhaps a factory object or maybe they extend your abstract class and provide a concrete constructor method.
Simple Factory - This isn't an official GoF pattern, infact I had no idea what you were talking about until I pulled out my Head First Design Pattern Book. Simple Factory is just a method that can return different hardcoded subtypes.
public Pizza createPizza(String type){
if(type.equals("cheese")){
return new CheesePizza();
}else if (type.equals("pepperoni")){
return new PepperoniPizza();
}
...
}
The problem with this code is you are stuck with only the hardcoded types. If you want to change how the method works, or what types are returned you have to modify code and recompile. Adding new types will be very difficult.
Factory Method - you do most of the work in a super class but put off deciding what sort of object you will be working with until runtime. Often the superclass needs to create a worker object of some default type but the superclass allows subclasses to specialize the worker. Factory Methods are usually used when an AbstractFactory is overkill but one downside is it forces you to use inheritance which has its own set of maintenance and design problems. This is very similar to SimpleFactory except you use inheritance instead of a discriminator to get different return types.
public void foo(){
Bar bar = createBar();
//do stuff with bar
}
//method is protected so subclass can override it to return something else
protected Bar createBar(){
return new DefaultBar();
}
AbstractFactory - Create Objects knowing only the interface they implement not the actual class. AbstractFactories make it easy for code to work in different systems because you don't need to know the concrete factory or concrete products that are used.
For example Collection.iterator()
is an abstract factory of Iterator
objects. Classes such as LinkedList
or HashSet
have their own implementations of iterator()
(and therefore are Concrete Factories) that return different classes that implement the iterator interface (the concrete product)
Once you finish Head First Design Patterns I recommend Holub on Patterns the code is a little dated (pre-generics) but you really learn a lot about how multiple patterns interact with one another in non-trivial code samples. The book only has 2 code samples which each cover about 10 patterns and take 100+ pages each to explain step by step
First of all , I don't see the "factory method pattern" as a standalone pattern (never headred of this pattern untill i've read wikipedia as you said in your question) . I see it more as a mix of factory pattern + strategy pattern .
You can imagine an object factory as a simple object creator .
When strategy pattern comes into play inside an object factory then you begin to add more logic about the creation of the object, to hide it from the client (the client should not know how the objects are created, leave this responsability to the factory).
A factory can be of many types (the decision of factory creation depends on many factors) :
- When thinking about object associations , an object may be composed by multiple objects . Here the root object may have a factory method that will create the need objects . This factory method is responsible for checking if the newly added objects keep the root in a valid state . So here the strategy pattern (factory method pattern as you call it) may come into play :
class Car {
public $carType;
public $audioSystem;
public function __construct($carType) {
$this->carType = $carType;
$this->audioSystemFactory();
}
public function audioSystemFactory() {
if ($this->carType == 'hipster') {
$this->audioSystem = new VynilPlayer();
}
else {
$this->audioSystem = new Mp3Player();
}
}
public function startMusic($albumName) {
$this->audioSystem->playSongs($albumName);
}
}
class VynilPlayer {
public $vynilAlbums = array('MJ TOP HITS', 'JUSTIN BIEBER TOP HITS');
public function playSongs($albumName) {
$this->loadVynil();
$this->startPlayer();
}
public function loadVynil() {
}
public function startPlayer() {
}
}
class Mp3Player {
public $dvdAlbums = array('MJ TOP HITS', 'JUSTIN BIEBER TOP HITS');
public function playSongs($albumName) {
$this->loadDVD();
$this->startPlayer();
}
public function loadDVD() {
}
public function startPlayer() {
}
}
You can also have a factory class that is responsible for the creation of only one type of object . You make a factory class per object type when the creation logic is very complex .
Even a primitive form of instanciation like a class constructor can be viewed as an object factory .
Factories are made to hide the implementation logic of some objects . You add strategy pattern to a factory to hide these details from the client .
Simple Factory:
Definition:
Creates objects without exposing the instantiation logic to the client. Refers to the newly created object through a common interface
public interface PaymentMethod {
public void makePayment();
}
class CreditCard implements PaymentMethod {
public void makePayment() {
System.out.println("Payment through credit card...");
}
}
class NetBanking implements PaymentMethod {
public void makePayment() {
System.out.println("Payment through net banking...");
}
}
public class PaymentMethodFactory {
public static PaymentMethod getPaymentMethod(String method) {
if ("creditcard".equalsIgnoreCase(method)) {
return new CreditCard();
} else if ("netbanking".equalsIgnoreCase(method)) {
return new NetBanking();
} else {
throw new IllegalArgumentException("Payment method not supported!");
}
}
}
public class SimpleFactoryTest {
public static void main(String[] args) {
PaymentMethodFactory factory = new PaymentMethodFactory();
PaymentMethod paymentMethod = factory.getPaymentMethod("creditcard");
paymentMethod.makePayment();
}
}
Factory Method:
Definition:
Defines an interface for creating objects, but let subclasses to decide which class to instantiate Refers the newly created object through a common interface.
public interface PaymentMethod {
public void makePayment();
}
class CreditCard implements PaymentMethod {
public void makePayment() {
System.out.println("Payment through credit card...");
}
}
class NetBanking implements PaymentMethod {
public void makePayment() {
System.out.println("Payment through net banking...");
}
}
public interface IPaymentMethodFactory {
public PaymentMethod getPaymentMethod();
}
class CreditCardFactory implements IPaymentMethodFactory {
public PaymentMethod getPaymentMethod() {
return new CreditCard();
}
}
class NetBankingFactory implements IPaymentMethodFactory {
public PaymentMethod getPaymentMethod() {
return new NetBanking();
}
}
public class FactoryMethodTest {
public static void main(String[] args) {
IPaymentMethodFactory factory = new CreditCardFactory();
PaymentMethod paymentMethod = factory.getPaymentMethod();
paymentMethod.makePayment();
}
}