Definition
Concept
Factory pattern: creational design pattern abstracting object instantiation. Provides interface for creating objects in superclass but allows subclasses to alter type of created objects.
Scope
Focus: object creation mechanism. Separation: creation logic from usage logic. Result: flexible, extensible code.
Context
Used when system requires dynamic object creation based on input or configuration without specifying exact class.
Purpose
Abstraction of Instantiation
Hide concrete classes. Client code interacts with interfaces or abstract classes.
Encapsulation of Creation Logic
Centralize creation code to reduce duplication and errors.
Support for Polymorphism and Extensibility
Enable adding new product types with minimal impact on existing code.
Types of Factory Patterns
Simple Factory
Not a formal pattern. Static method creates instances based on parameters.
Factory Method
Defines interface for creating an object but lets subclasses decide which class to instantiate.
Abstract Factory
Creates families of related objects without specifying concrete classes.
Structure
Participants
Product: interface or abstract class defining object. ConcreteProduct: implements Product. Creator (Factory): declares factory method. ConcreteCreator: overrides factory method to return ConcreteProduct.
Collaborations
Client uses Creator interface to create Product. Creator delegates instantiation to ConcreteCreator.
UML Overview
Factory method pattern: Creator contains factoryMethod(). ConcreteCreator implements factoryMethod() to instantiate ConcreteProduct.
| Component | Role |
|---|---|
| Product | Defines interface for objects |
| ConcreteProduct | Implements Product interface |
| Creator (Factory) | Declares factory method |
| ConcreteCreator | Overrides factory method to instantiate ConcreteProduct |
Implementation Details
Factory Method Signature
Return type: Product interface or abstract class. Parameters: optional, to decide concrete product.
Subclassing
ConcreteCreator subclasses override factory method to instantiate specific ConcreteProduct.
Client Interaction
Client calls factory method via Creator interface, unaware of concrete class.
abstract class Creator { abstract Product factoryMethod(); void someOperation() { Product product = factoryMethod(); // Use product }}class ConcreteCreator extends Creator { Product factoryMethod() { return new ConcreteProduct(); }}Advantages
Decoupling
Separates client code from concrete classes.
Extensibility
New products added without modifying client or factory interface.
Single Responsibility
Factory encapsulates creation logic, promoting cleaner code.
Testability
Mock factories enable easier unit testing.
Disadvantages
Increased Complexity
Additional classes and interfaces increase code base size.
Overhead
Factory indirection adds runtime overhead and cognitive load.
Potential for Misuse
Unnecessary abstraction if few product variants exist.
Usage Scenarios
When to Use
System requires flexible object creation. New product types expected. Client unaware of concrete classes.
Where to Avoid
Simple instantiation suffices. No foreseeable product changes.
Common Applications
GUI toolkit widgets, database drivers, cross-platform resource loading.
Comparison with Other Patterns
Simple Factory vs Factory Method
Simple Factory: static method, no inheritance. Factory Method: relies on subclassing.
Factory Method vs Abstract Factory
Factory Method: creates one product. Abstract Factory: creates families of related products.
Factory vs Builder
Factory: creates objects in one step. Builder: creates complex objects step-by-step.
Code Example
Scenario
Shape creation with Factory Method pattern.
Classes
Shape (interface), Circle and Square (concrete), ShapeFactory (creator), CircleFactory and SquareFactory (concrete creators).
interface Shape { void draw();}class Circle implements Shape { public void draw() { System.out.println("Drawing Circle"); }}class Square implements Shape { public void draw() { System.out.println("Drawing Square"); }}abstract class ShapeFactory { abstract Shape createShape(); void render() { Shape shape = createShape(); shape.draw(); }}class CircleFactory extends ShapeFactory { Shape createShape() { return new Circle(); }}class SquareFactory extends ShapeFactory { Shape createShape() { return new Square(); }}// Client codeShapeFactory factory = new CircleFactory();factory.render(); // Outputs "Drawing Circle"Best Practices
Interface Consistency
Factory methods should maintain consistent signatures for ease of use.
Avoid Over-Generalization
Do not abstract prematurely; apply factory only when multiple products exist.
Documentation
Clearly document factory responsibilities and product variants.
Unit Testing
Mock factories to isolate tests from concrete implementations.
References
- Gamma, E., Helm, R., Johnson, R., Vlissides, J., "Design Patterns: Elements of Reusable Object-Oriented Software," Addison-Wesley, 1994, pp. 87-122.
- Freeman, E., Robson, E., Bates, B., Sierra, K., "Head First Design Patterns," O'Reilly Media, 2004, pp. 75-110.
- Shalloway, A., Trott, J.R., "Design Patterns Explained: A New Perspective on Object-Oriented Design," Addison-Wesley, 2002, pp. 45-70.
- Martin, R.C., "Agile Software Development, Principles, Patterns, and Practices," Prentice Hall, 2003, pp. 150-165.
- Buschmann, F., Meunier, R., Rohnert, H., Sommerlad, P., Stal, M., "Pattern-Oriented Software Architecture: A System of Patterns," Wiley, 1996, pp. 123-140.