Engineering Full Stack Apps with Java and JavaScript
There are different types of factory patterns like Simple Factory (Or Class Factory), Factory Method, Abstract Factory Method and Creator Method (Or Static Factory Method). Out of these, Factory Method and Abstract Factory Method are part of the GoF Design Patterns. All factory design patterns help you create objects without using the new keyword directly within your code. Concept is similar to any other real world factories: You use cars, but you don’t develop cars by your own. Instead, a car factory will create a specific type of car with the common properties and behaviors of a car.
Factory pattern is primarily based on the design principle to encapsulate and separate the aspects of your application that vary from what stays the same. The decision on which concrete implementation of a class to use may change later and we can make use of the design principle program to an interface to separate from the core program logic. Even if you have an interface reference type pointing to a concrete instantiation using “new”, you will still need to change your code to change the concrete class, which is against the ‘closed for modification’ part of the Open Close Principle. Factory pattern is an alternative to constructors. You should always try to provide factories instead of, or in addition to, constructors, for your class.
Simple Factory will encapsulate the object creation and will separate it out into a separate class of its own. The sole purpose of that class would be to create objects based on some criteria provided.
Example:
Consider a Shape interface and its implementations.
interface Shape{
public void draw();
}
class Rectangle implements Shape
{ // implementation details are not shown
}
class Circle implements Shape
{ // implementation details are not shown
}
class SimpleShapeFactory
{
//other implementation details are not shown
public static getShape(String type) throws SomeCustomException
{
if(type.equals(“circle”)
return new Circle();
else if(type.equals(“rectangle”)
return new Rectangle();
else
throw SomeCustomException(“Invalid Shape”);
}
}
Client code
Shape shape = SimpleShapeFactory.getShape(type);
Factory method pattern is polymorphic. Factory method pattern create an abstraction to create objects and defer instantiation to subclasses thus allowing subclasses to decide which class to instantiate. Instead of separating the instantiation into a separate class of its own (as in Simple Factory), the factory method pattern will add an abstract factory method to the client class itself (also making the client class as abstract) and then any of this class’s concrete subclasses can implement the abstract factory method as needed and return the right implementation.
Factory method pattern makes use of the inheritance feature of Object Oriented Programming languages to attain code reuse and gives a lot of flexibility, and also avoids the need for a separate class for instance creation.
Example:
In the Shape example, instead of having a separate Shape Factory, we can create a new abstract method getShape() within the client class (also making the client class as abstract) and then call it as below.
Client Code
Shape shape = getShape(type);
Where getShape() is an abstract method of the client class. Any of this class’s concrete subclasses can implement the abstract factory method as needed and return the right implementation.
In a creator method or static factory, the factory method will be static and we can call this static method to create an instance of an object we require. The singleton pattern makes uses of the static factory, as the static getInstance() method of the Singleton class create and maintain an object and return it whenever someone ask for that instance.
A problem with static factory is that you cannot subclass and change the behavior of the create method. For singleton pattern, this was done with a purpose so that no one will override the singleton behavior by creating a subclass.
The abstract factory pattern provides a way to encapsulate a group of similar or related factories. Abstract factory can be considered as a factory of factories. In abstract factory pattern, a client first need to request a concrete implementation of a factory from the abstract factory object, and then it requests an appropriate object from this factory object.
Use of abstract factory pattern allows us to change concrete implementations of the factory itself without changing the code that uses them.
Disadvantage of the abstract factory pattern is that, it may result in extra complexity and extra work in the initial writing of code, and can result in systems which are more difficult to debug and maintain.
Example:
We will just expand on the previous example with Shape interface, Circle class and Rectangle class.
Consider a case where the code to draw a circle/rectangle is different for windows and Linux. In such a case, we can create two factories: WindowsShapeFactory and LinuxShapeFactory. WindowsShapeFactory will return a shape with drawing code specific to windows and the LinuxShapeFactory will return a shape with drawing code specific to Linux.
The abstract factory ShapeFactory will return a WindowsShapeFactory or LinuxShapeFactory based on the operating system and then you can ask this returned factory for a Shape object the same way as you did with the ShapeFactory before.
This is just a quick comparison of the four related but often confusing factory design patterns. Some even don't consider the Static Factory and Simple Factory as patterns at all, but it is good to know at least the differences between all these terms anyway.
Head First Design Patterns By Eric Freeman, Elisabeth Freeman, Bert Bates, Kathy Sierra