Factory Method
Let a superclass define how a product is used while subclasses decide which concrete product gets created.
The problem
Version one of your logistics app moves cargo by truck, so Truck is everywhere. Then the
sea freight companies come knocking, and it turns out most of your codebase has quietly
memorized the word Truck. Adding Ship means editing all of it. Add rail after that and
you do the whole tour again.
The result is code marbled with conditionals that switch behavior based on the class of the transport object. Every new carrier widens every branch.
The solution
Stop calling new Truck() in the middle of your business logic. Replace direct
construction with a call to a factory method. The new operator still runs, it just
runs inside that one method, and the objects it returns are called products.
The payoff arrives when a subclass overrides the factory method and returns a different
product. RoadLogistics.createTransport() returns a truck, SeaLogistics.createTransport()
returns a ship, and planDelivery() in the base class never notices. One requirement makes
this work: all products implement a common interface, and the factory method's declared
return type is that interface.
- 1The application reads a config and picks a creator subclass. This is the only place a concrete choice is made.
- 2From here on the client talks to the base type. It sees Logistics, not SeaLogistics.
- 3The business logic calls its own factory method. Polymorphism routes the call to the subclass override.
- 4The subclass is the only code in the building that knows the word "Ship".
- 5It comes back typed as the interface, so the base class stays blissfully ignorant of what it received.
- 6The shared logic runs against the interface. Same method call would have moved a truck.
Structure
Four moving parts: the product interface, the concrete products, the creator that declares the factory method, and the concrete creators that override it. Declare the base factory method abstract to force every subclass to answer the question, or give it a body to provide a sensible default product.
Code
Same example three ways: a logistics planner that works with trucks or ships without ever naming one.
When to use it
- You do not know upfront the exact types your code will need to instantiate. New product types then arrive as a new creator subclass rather than an edit to existing code.
- You ship a library or framework and want users to extend its internals. They subclass the component and override the factory method that builds it, and the framework picks up their version.
- You want to reuse expensive objects such as connections or file handles. A constructor must return something new; a factory method may hand back a pooled instance.
Pitfalls
- Subclass explosion. One creator subclass per product adds up. If the products are numerous and boring, a parameterized factory method beats a dozen near-empty classes.
- A giant switch in the base method. During refactoring, the factory method often grows a switch over a control parameter. That is a legitimate way station, not a destination.
- Forgetting the return type. Declare the factory method as returning the concrete class and the coupling you just removed walks straight back in.
Don't confuse it with
- Abstract Factory. Many designs start with Factory Method because it is simple and subclass-customizable, then evolve toward Abstract Factory when one product stops being enough. Keep bolting factory methods onto one creator and you have essentially arrived.
- Prototype. Prototype avoids inheritance entirely by cloning a configured instance, at the price of a fussier initialization step. Factory Method leans on inheritance but needs no such setup.
- Template Method. Factory Method is a specialization of Template Method where the overridable step happens to return an object. It can equally serve as one step inside a larger template.
Check yourself
What has to be true about the objects a factory method returns?