Factory Method Pattern
Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory method lets a class defer instantiation to subclasses.
Concept
In factory method pattern, we create an abstract creator class that defines a basic structure of application and the subclasses which derive from this abstract class perform the actual instantiation process. The concept makes more sense to you as you read through the analogy, class diagrams and examples.
Factory method pattern is the extension of simple factory pattern
Read about simple factory pattern
In the simple factory pattern, we simply segregate the instantiation logic from client code where it knows about all the classes whose objects it can create.
On the other hand, when using a factory method pattern, you delegate the object creation to subclasses. Also, the factory method is not absolutely sure about the product subclasses in advance.
Note: The key aim of the factory method pattern is that it is supplying the framework through which different subclasses can make different products. But in a simple factory, you cannot vary the products like you can with the factory method pattern.
Think of simple factory as a one-time deal but most importantly, your creational part will not be closed for modification. Whenever you want to add a new stuff, you need to add an if..else
block or a switch
statement in the factory class of your simple factory pattern.
In this context, remember the GoF definition - the factory method lets a class defer instantiation to subclasses.
So, in our simple factory pattern demonstration, you used a concrete class only (SimpleFactory
). You did not need to override the createAnimal()
method and there was no subclass that participated in the final decision/product making process. But if you try to code to an abstract class (or interface
), that is always considered a good practice, and this mechanism provides you the flexibility to put some common behaviors in the abstract class.
Analogy
Consider a car manufacturer who produces the different car models as per customer preferences. For different car models, manufacturer uses different parts. In the future, the manufacturer should be able to replace the car parts with newly designed models. This is the perfect analogy of factory method pattern. Here, CarFactory
can be the abstract factory and each factory model extends CarFactory
.
Implementation In Java
Factory method pattern is the extension of simple factory pattern. Let’s extend the same example from simple factory pattern.
Class Diagram
Factory pattern has two parallel hierarchies. One for factory classes and another for object producing classes.
In our case, classes in factory method pattern incudes,
classDiagram
class Client {
+process()
}
class AnimalFactory {
+AnimalFactory()
+createAnimal()* Animal
}
class DogFactory {
+DogFactory()
+CreateAnimal() Animal
}
class CatFactory {
+CatFactory()
+CreateAnimal() Animal
}
class Animal {
<<interface>>
+speak()
+eat()
}
class Dog {
+Dog()
+speak()
+eat()
}
Client --> AnimalFactory
AnimalFactory --|> DogFactory
AnimalFactory --|> CatFactory
Animal <|-- AnimalFactory
Animal <|.. Dog
Animal <|.. Cat
Illustration
In the above class diagram, there are two class hierarchies. One class hierarchy is for AnimalFactory
related classes and another is for Animal
related classes.
AnimalFactory
classes uses Animal
classes to create objects as client specified.
AnimalFactory
is an abstract class. DogFactory
and CatFactory
extends AnimalFactory
and implements createAnimal()
method.
Animal
classes is an interface. Dog
and Cat
implements the speak()
and eat()
methods as they implements Animal
.
Client
uses concrete factory classes like CatFactory
and DogFactory
to create Animal
type objects (Dog
and Cat
).
Implementation
Following code blocks are the classes implementations for factory method pattern
AnimalFactory
AnimalFactory.java implementation
abstract class AnimalFactory {
// abstract factory to create animal
public abstract Animal createAnimal();
}
DogFactory
DogFactory.java implementation
class DogFactory extends AnimalFactory {
// creates dog object
@Override
public Animal createAnimal() {
return new Dog();
}
}
CatFactory
CatFactory.java implementation
class CatFactory extends AnimalFactory {
// creates cat object
@Override
public Animal createAnimal() {
return new Cat();
}
}
Animal
Animal.java implementation
interface Animal {
// interface methods
void speak();
// interface default method
default void eat() {
System.out.println("Yum! Yum!");
}
}
Dog
Dog.java implementation
class Dog implements Animal{
// Dog implementation extends Animal
public Dog() {}
@Override
public void speak() {
System.out.println("Bow! Bow!");
}
}
Cat
Cat.java implementation
class Cat implements Animal{
// Cat implementation extends Animal
public Cat() {}
@Override
public void speak() {
System.out.println("Meow! Mewo!");
}
}
Client
Client.java implementation
class Client {
public void process() {
AnimalFactory dogFactory = new DogFactory();
Animal dog = dogFactory.createAnimal();
dog.speak();
dog.eat();
AnimalFactory catFactory = new CatFactory();
Animal cat = catFactory.createAnimal();
cat.speak();
dog.speak();
}
}
Reason for creating createAnimal()
method in Client
class is intentional. The intention is to create specialized objects using subclasses.
If we look carefully, only the creational part
is varying across the products.
Advantages
Separating code that can vary from the code that does not vary (i.e., the advantages of using a simple factory pattern is still present). This technique helps you easily maintain code.
The code is not tightly coupled. So, you can add new classes like Lion, Beer, and so forth, at any time in the system without modifying the existing architecture. So, you have followed the
closed for modification but open for extension
principle.
Disadvantages
- The factory method pattern involves creation of many classes. If the number of classes increases, it can add up the code maintenance efforts.
When To Use
- When client does not know which class it may require at runtime.
- A class wants its subclasses to specify the objects it creates.
- When you want to encapsulate the object creation process.
- Object instance needs to be initialized with some data is not available to the client.
- Object instantiation requires a lot of data and there are a lot of variations based on the data. Instead, proved static factory methods that create the instance based on the different variations.
Known Uses
Factory method pattern is used in many frameworks and is also incorporated into core language structure.
Java
Following are the factory method examples used in java language.
java.util.Calendar#getInstance()
java.util.ResourceBundle#getBundle()
java.text.NumberFormat#getInstance()
java.nio.charset.Charset#forName()
java.net.URLStreamHandlerFactory#createURLStreamHandle (String) // Returns singleton object per protocol
java.util.EnumSet#of()
javax.xml.bind.JAXBContext#createMarshaller() // and other similar methods
Related Patterns
- The factory Method has a lot of variations. It can return a new object or same instance multiple times, or can return a subclass object by extending a new class.
- Factory Method is usually called through the
template method
and is usually a hook that subclasses can override for custom implementation. - Used to implement
abstract factory
. - Factory method has to be subclasses if it has to return a new object. Prototype pattern don’t require a new class. It requires a new object.
- Prototype pattern require initialize operations after returning an instance. Factory method don’t require such operation.