What Is the Factory Pattern?
The factory pattern is a creational design pattern that provides a single interface for creating objects without exposing the concrete classes that are instantiated. The client code requests an object by specifying a key or type, and the factory decides which concrete class to instantiate.
Why Use the Factory Pattern?
- Encapsulation of creation logic: Complex or conditional object construction is centralized.
- Reduced coupling: Client code depends on abstractions rather than concrete implementations.
- Improved maintainability: Adding new product types requires changes only in the factory.
- Enhanced testability: Factories can be mocked or substituted in unit tests.
How to Implement a Simple Factory in Python
A basic factory uses a static method that maps a string identifier to a concrete class and returns an instance.
- Define the product interface (e.g., a base class or protocol).
- Create concrete product classes that implement the interface.
- Implement a factory class with a
createmethod that selects the appropriate class.
Cleaner Factory Using a Dictionary
Replacing long if‑elif chains with a dictionary improves readability and extensibility.
- Store the mapping
{"key": ConcreteClass}as a class attribute. - Retrieve the class with
dict.get(key)and instantiate it.
Factory with Parameters
When products require initialization arguments, the factory forwards those parameters during instantiation.
- Accept
*argsand**kwargsin the factory method. - Pass them to the selected class constructor.
Using Abstract Base Classes with Factories
Abstract Base Classes (ABCs) enforce a common interface across all products, guaranteeing that the factory returns a compatible object.
- Define an ABC with
@abstractmethoddefinitions. - Make concrete products inherit from the ABC.
- The factory returns objects typed as the ABC, enabling static type checking.
Practical Example: Database Connection Factory
A real‑world factory can create connections for different databases (e.g., SQLite, PostgreSQL, MySQL) based on configuration data.
- Define a
DatabaseConnectionABC withconnectandclosemethods. - Implement concrete connection classes for each database engine.
- The factory provides
create_connection(type, **settings)andcreate_from_config(config_dict)methods.
When to Apply and When to Avoid the Factory Pattern
Use the factory pattern when:
- Multiple related classes share a common interface.
- The concrete class to instantiate is determined at runtime.
- Object creation involves non‑trivial logic or configuration.
Avoid it when:
- Only one or two simple classes exist.
- Creation logic is straightforward and adds no value.
- The extra abstraction would obscure the code’s intent.