Here I will explain the difference between Simple Factory & Factory Method design patterns. There are two things:
- People confuse Simple Factory & Factory Method to be same.
- And those who know the difference between Simple Factory & Factory Method, doesn’t know the different use cases where these two are applicable.
Simple Factory:
Simple Factory is not an official design pattern. It is more of a design principle that you should follow as part of Object Oriented design. One should code to interface, not to concrete implementation. That is the basic OOPs concept. That way, we can add any new sub types (subclass) easily without modifying existing code in multiple places. Simple factory helps in achieving that.
public interface ElectronicToy {
public void switchOn();
public void switchOff();
}
public class Gun implements ElectronicToy {
public void switchOn() {
System.out.println("Gun on");
}
public void switchOff() {
System.out.println("Gun off");
}
}
public class Doll implements ElectronicToy {
public void switchOn() {
System.out.println("Play");
}
public void switchOff() {
System.out.println("Stop");
}
}
public class ToyFactory() {
private ToyFactory() {}
public static ElectronicToy makeToy(String type) {
if ("gun".equals(type)) {
return new Gun();
} else if ("doll".equals(type)) {
return new Doll();
}
}
}
ToyFactory class above is the Simple Factory. Two main things are accomplished above.
- We are returning object with common interface type. So the clients of the Factory don’t need to know the actual sub type. The knowledge of actual concrete classes is encapsulated within the simple factory class.
- If one more sub type is added, only factory class will have to be changed. There won’t be any other modification within the existing code.
So Simple Factory helps in adhering to OOPs design principle.
Factory Method:
Factory Method pattern has a different use case. This pattern provides an interface to create objects. But it lets subclasses of that interface to decide which concrete object to instantiate. Basically we have a factory class. But it is abstract. We have concrete implementation of that factory class which takes care of particular type of object creation.
Why do we need that? For the use case described above in Simple Factory section, we don’t need that. It will just be an overkill. Then what are the use cases? Let’s say we have a factory where a toy can be ordered. Order process has multiple steps. Suppose we have two different production houses where two different types of toys are made, one is standard type & other is luxury type. But other steps in ordering process like packing & shipping remain same. And we want our order process to remain consistent as both production houses belong to same company. Only the toy object gets changed based on the factory where it is made.
In this scenario, we can use Factory Method pattern. We define an abstract ToyFactory class which encapsulates the internal order steps. Factory method makeToy() is defined as abstract method which will be implemented in concrete ToyFactory subclasses like StandardToyFactory & LuxuryToyFactory.
public abstract class ToyFactory {
public void order(String type) {
ElectronicToy toy = makeToy(type);
pack(toy);
ship(toy);
}
public abstract ElectronicToy makeToy(type);
private void pack(ElectronicToy toy) {
System.out.println("packed");
}
private void ship(ElectronicToy toy) {
System.out.println("shipped");
}
}
public class StandardGun extends Gun {
}
public class LuxuryGun extends Gun {
}
public class StandardDoll extends Doll {
}
public class LuxuryDoll extends Doll {
}
public class StandardToyFactory extends ToyFactory {
public ElectronicToy makeToy(type) {
if ("gun".equals(type)) {
return new StandardGun();
} else if ("doll".equals(type)) {
return new StandardDoll();
}
}
}
public class LuxuryToyFactory extends ToyFactory {
public ElectronicToy makeToy(type) {
if ("gun".equals(type)) {
return new LuxuryGun();
} else if ("doll".equals(type)) {
return new LuxuryDoll();
}
}
}
As you can see above, the concrete factory subclass just needs to define the makeToy() method based on the factory where it is made. But the order() method flow remains same & factory subclass doesn’t have ownership to change the flow. That’s how different types of objects are created but the processing of those objects based on business rules remain same.
Summary:
So to summarize, if you just need to encapsulate object creation, you can use Simple Factory. But if you have additional process or flow that acts upon the newly created object & you want to make sure that the process remains same across the system, you should think about implementing Factory Method design pattern.