
The Factory Method Pattern is a creational design pattern that provides an interface for creating objects in a superclass but allows subclasses to alter the type of objects that will be created. It enables a class to delegate the responsibility of instantiation to its subclasses.
What is the Factory Method Pattern?
The Factory Method Pattern is used to define an interface for creating an object but let subclasses alter the type of objects that will be created. This pattern allows a class to defer the instantiation of its objects to subclasses.
Key Components
- Product: An interface or abstract class defining the type of object to be created.
- ConcreteProduct: A class that implements the
Product
interface, representing a specific type of object. - Creator: An abstract class or interface declaring the factory method, which returns a
Product
object. It may also define a default implementation for the factory method. - ConcreteCreator: A class that implements the
Creator
interface and overrides the factory method to return an instance ofConcreteProduct
.
Why Use the Factory Method Pattern?
The Factory Method Pattern is used for the following reasons:
- Encapsulation: It encapsulates the creation logic of objects, which can be complex or involve several steps.
- Flexibility: It allows subclasses to alter the type of objects that will be created without changing the code of the class that uses the factory.
- Single Responsibility Principle: It separates the responsibility of creating objects from their usage, adhering to the Single Responsibility Principle.
Implementing the Factory Method Pattern
Basic Implementation
Hereβs a basic implementation of the Factory Method Pattern in Java:
// Product Interface
public interface Product {
void use();
}
// ConcreteProduct Implementation
public class ConcreteProductA implements Product {
@Override
public void use() {
System.out.println("Using ConcreteProductA");
}
}
public class ConcreteProductB implements Product {
@Override
public void use() {
System.out.println("Using ConcreteProductB");
}
}
// Creator Abstract Class
public abstract class Creator {
public abstract Product factoryMethod();
public void doSomething() {
Product product = factoryMethod();
product.use();
}
}
// ConcreteCreator Implementations
public class ConcreteCreatorA extends Creator {
@Override
public Product factoryMethod() {
return new ConcreteProductA();
}
}
public class ConcreteCreatorB extends Creator {
@Override
public Product factoryMethod() {
return new ConcreteProductB();
}
}
In this example:
- Product Interface: Defines the operations that can be performed on products.
- ConcreteProduct: Implements the
Product
interface. - Creator: Declares the factory method
factoryMethod()
that returns aProduct
object. - ConcreteCreator: Implements the factory method to return a specific
ConcreteProduct
instance.
Advantages
- Flexibility in Object Creation: Allows different implementations of
Product
to be created without altering theCreator
class. - Encapsulation: The creation logic is encapsulated in subclasses, making it easier to manage and extend.
Example Usage
public class Main {
public static void main(String[] args) {
Creator creatorA = new ConcreteCreatorA();
creatorA.doSomething();
Creator creatorB = new ConcreteCreatorB();
creatorB.doSomething();
}
}
In this usage example, ConcreteCreatorA
and ConcreteCreatorB
both use their respective factoryMethod()
to create and use different Product
instances.
Common Use Cases
The Factory Method Pattern is commonly used in scenarios where:
- Class Instantiation: There is a need to instantiate classes that share a common interface but have different implementations.
- Frameworks and Libraries: Frameworks provide base classes with factory methods that subclasses implement to create objects specific to their needs.
- Object Creation Logic: The creation logic involves several steps or configurations that can vary based on conditions or parameters.
Frameworks and Libraries
In frameworks, the Factory Method Pattern is used to provide extensibility points where users can create instances of specific classes without modifying the framework code. For example, in a GUI framework, a base Dialog
class might have a factory method to create different types of dialogs based on the context.
Configuration-Based Object Creation
The pattern is used when the type of object to be created is determined based on configuration files or user inputs. For instance, a reporting application might use a factory method to create different types of report formats based on user selection.
Comparing Factory Method Pattern to Other Patterns
Factory Method vs. Abstract Factory Pattern
While both patterns deal with object creation, the Factory Method Pattern focuses on creating a single object with a common interface. In contrast, the Abstract Factory Pattern provides a way to create families of related or dependent objects. The Factory Method Pattern is used for creating one type of object, whereas the Abstract Factory Pattern creates a group of related objects.
Factory Method vs. Builder Pattern
The Factory Method Pattern creates objects through a factory method, whereas the Builder Pattern constructs complex objects step-by-step. The Factory Method Pattern is used for creating instances of a single object type, while the Builder Pattern is used for assembling complex objects with multiple components.
Factory Method vs. Prototype Pattern
The Prototype Pattern creates new objects by copying an existing object (prototype), whereas the Factory Method Pattern creates new objects through a factory method. The Prototype Pattern is used when creating new instances by cloning is more efficient, while the Factory Method Pattern provides flexibility in object creation.
Best Practices for Using Factory Method Pattern
- Encapsulation: Ensure that the object creation logic is encapsulated within the factory method.
- Single Responsibility Principle: Keep the factory method focused on object creation and avoid mixing it with other responsibilities.
- Avoid Overuse: Use the Factory Method Pattern when it provides clear benefits in managing object creation and instantiation.
- Consider Alternatives: Evaluate other design patterns like Abstract Factory or Builder when dealing with complex object creation scenarios.
Conclusion
The Factory Method Pattern provides a flexible way to create objects through an interface, allowing subclasses to alter the type of objects that will be created. It promotes encapsulation and adheres to the Single Responsibility Principle. Understanding its implementation and use cases is essential for effective application in software design.
For further reading, consider exploring Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides.