Every codebase reaches a point where the simple new keyword becomes a liability. What starts as a straightforward instantiation grows tentacles: conditional logic, configuration parameters, dependency injection, and knowledge of concrete classes leaking across module boundaries.
The factory family of patterns addresses this friction. Rather than scattering construction logic throughout your codebase, factories centralize the decision of which object to create and how to create it. Callers request what they need; factories decide how to satisfy that request.
But not all factories are equal. The Gang of Four described two distinct patterns—Factory Method and Abstract Factory—while practitioners commonly employ a third variant, the Simple Factory, that doesn't appear in the classic literature. Choosing among them requires understanding the specific problem each solves. Applying the wrong variant introduces unnecessary complexity; applying the right one clarifies intent and stabilizes design under change.
Factory Method: Deferring Creation to Subclasses
The Factory Method pattern defines an interface for creating an object but lets subclasses decide which class to instantiate. A base class declares an abstract creation method; concrete subclasses override it to return specific product types. The pattern shines when a class must produce objects whose exact type cannot be known at the point of definition.
Consider a document editor framework. The base Application class knows it must create documents, but the specific document type—text, spreadsheet, drawing—depends on the concrete application. Rather than embedding conditional logic, the framework declares createDocument() as a hook. Each concrete application overrides it, and the base class orchestrates behavior through this indirection.
The critical insight is that Factory Method leverages polymorphism to invert control over instantiation. The framework calls into subclasses without knowing their identity. This aligns with the Open-Closed Principle: adding a new document type means adding a new subclass, not modifying existing code.
The cost is structural. Factory Method requires an inheritance hierarchy that mirrors your product hierarchy. If you don't already have such a hierarchy for other reasons, introducing one solely to enable a factory is overkill. Use this pattern when subclassing is already justified and you need each subclass to control the concrete types it works with.
TakeawayFactory Method is polymorphism applied to construction itself. It fits naturally when your architecture already relies on inheritance to vary behavior—forcing it in flatter designs creates hierarchies that exist only to serve the pattern.
Abstract Factory: Families of Related Products
Abstract Factory operates at a higher level of abstraction. Rather than creating a single product, it creates families of related products that must work together. A UI toolkit might need buttons, scrollbars, and windows that share a visual style; a persistence layer might need connections, statements, and result sets that all target the same database vendor.
The pattern defines an abstract factory interface declaring creation methods for each product in the family. Concrete factories implement this interface, ensuring internal consistency: a MacFactory produces only Mac-style widgets, never mixing them with Windows counterparts. Client code depends only on abstract interfaces, remaining oblivious to which family is in use.
The power of Abstract Factory lies in enforcing compatibility constraints through the type system. Once a client obtains a factory, every product it creates is guaranteed to belong to the same family. This eliminates an entire category of runtime errors where incompatible components are combined by accident.
The trade-off is rigidity. Adding a new product to the family requires modifying the abstract factory interface and every concrete implementation—a violation of the Open-Closed Principle in one dimension to gain flexibility in another. The pattern is worthwhile when product families change together as coherent units, not when individual products evolve independently.
TakeawayAbstract Factory trades flexibility along one axis for guarantees along another. It's the right choice when the cohesion of a product family matters more than the ease of adding new product types.
Simple Factory: Pragmatism Over Purity
The Simple Factory isn't a Gang of Four pattern—it's a technique. Typically implemented as a static method or a dedicated class with creation logic, it centralizes object construction without the ceremony of inheritance hierarchies or interface families. A single method takes a parameter or configuration and returns the appropriate concrete type.
Its value is proportional to its modesty. When you have a small, stable set of variants and want to isolate the new keyword from your business logic, Simple Factory does the job with minimal overhead. It gives you a single place to modify when creation logic changes, without imposing an architectural pattern that must be understood and maintained.
The limitation is honest: Simple Factory doesn't support extension without modification. Adding a new type means editing the factory itself, typically its conditional logic. This is acceptable when the set of variants changes rarely and the cost of modification is contained. It becomes painful when variants proliferate or when third parties need to add their own.
Experienced designers reach for Simple Factory first and escalate only when justified. Reaching immediately for Factory Method or Abstract Factory in situations that don't demand them is a form of pattern-driven overengineering—complexity purchased with no return.
TakeawayPatterns are tools, not badges. The best design uses the least machinery necessary to solve the problem, and Simple Factory is often exactly enough.
The factory patterns represent a spectrum of solutions to a single problem: separating what is created from where it is used. Each variant offers different guarantees at different costs.
Choose Simple Factory when creation logic needs centralization but not extensibility. Choose Factory Method when an existing inheritance hierarchy needs polymorphic construction. Choose Abstract Factory when families of products must remain consistent across variations.
The deeper principle is architectural humility. Patterns solve specific problems—their value evaporates when applied speculatively. Study the forces at play in your design, apply the lightest tool that resolves them, and let complexity earn its place in your codebase rather than assuming it.