Design Pattern Evangelist Blog

Smart pointers about software design

Maintained by Jim Humelsine | RSS Feed | Edit on GitHub

An Introduction to Creational Design Patterns

Different mechanisms to create objects without calling new() directly


God creating heaven and earth

Introduction

After a year-long diversion into Automated Testing, I’ve completed the series, and I’m returning to Design Patterns with a series on Creational Design Patterns.

If you’ve ever wrestled with unwieldy constructors or tangled initialization logic, Creational Design Patterns offer proven solutions. Creational Design Patterns help software engineers control object creation, ensuring flexibility, testability, and scalability. Whether you need a single shared instance, a family of related objects, or assembled objects configured from a blueprint, these patterns offer time-tested solutions to common problems of initialization and configuration.

This series will walk you through several core patterns—what they are, when to use them, and how they simplify your code.

The Gang of Four’s Creational Design Patterns

The Gang of Four (GoF) organized their catalog of Design Patterns into three major categories, with the first category being the Creational Design Patterns. The other two are Structural Design Patterns and Behavioral Design Patterns. Structural patterns focus upon the organization of objects, and behavioral patterns focus upon their behaviors. Quite frankly, I’ve often felt like the GoF’s assignment of design patterns between the structural and behavior categories was somewhat arbitrary, which is why I don’t tend to focus upon their categorization.

I introduced the Gang Of Four Creational Design Pattern Inventory as a section within the Factory Design Pattern, but I didn’t provide too much detail. I’ll provide more details in subsequent blogs in this series.

These are patterns that allow the caller to acquire an object without being coupled to the class type for the object returned. The caller will reference the objects as an abstraction, such as an interface, which aligns with the GOF’s first design principle: Program to an interface, not an implementation.

Programming to an interface decouples software components and encourages a more modular design. It allows different class types to satisfy the caller’s reference including Test Doubles which makes testing easier.

The Creational Design Patterns

The GoF cataloged five Creational Design Patterns. I include a few more. Here is my set, each of which will link to a blog dedicated to that pattern when written:

What the GoF Missed

The GoF missed a few things, which I’ve addressed previously:

Creational Design Patterns Are Not Mutually Exclusive

Creational Design Patterns are not mutually exclusive. They can work together. For example, Builder could be used to create and assemble a Composite Tree. The Non-Terminal Nodes in this tree could be created using Factory Methods, and the Terminal Leaf Nodes could be created using Singletons or Flyweights.

Summary

Creational Design Patterns give us proven strategies for managing object creation, whether we need strict control, flexibility, or scalability. From ensuring a single instance with Singleton to constructing complex objects with Builder, each pattern addresses a unique design challenge. Mastering these patterns equips developers to write cleaner, more maintainable code — and to choose the right tool for the right job.

Pattern Purpose Key Features Advantages Disadvantages Common Use Cases
Factory Encapsulates object creation logic in a separate method or class Returns instances of a common interface or superclass; creation is delegated to a factory method Reduces duplication of creation code; decouples client from concrete classes May introduce many small factory classes; can obscure which class is actually created GUI components, parsers, game entities
Abstract Factory Creates families of related or dependent objects without specifying concrete classes Provides an interface for creating multiple products; each factory corresponds to a product family Ensures compatibility among created objects; promotes consistency Can be complex when many products are involved; adding products can require significant changes UI themes, cross-platform toolkits, data access layers
Builder Separates the construction of a complex object from its representation Step-by-step object creation; same construction process can create different representations Simplifies creation of complex objects; improves code readability More verbose; may be overkill for simple objects Document generation, assembling meals in food ordering apps, constructing complex game objects
Singleton Ensures a class has only one instance and provides a global point of access Private constructor, static instance, controlled access Controlled access to a shared resource; can reduce memory usage for heavy objects Can hide dependencies; difficult to test; potential global state issues Logging, configuration settings, thread pools
Flyweight Reduces memory usage by sharing common parts of object state Separates intrinsic (shared) and extrinsic (context-specific) state Greatly reduces memory footprint; improves performance for large numbers of similar objects Increases code complexity; requires careful separation of state Text rendering (character glyphs), game sprites, caching
Prototype Creates new objects by cloning existing ones Uses a prototypical instance to create new objects Can simplify creation of complex objects; avoids subclassing for new configurations Cloning can be tricky with deep copies or complex structures Document templates, game entity replication, UI element duplication
Object Pool Manages a set of reusable objects to avoid costly creation/destruction Keeps track of available and in-use objects; returns them to pool after use Improves performance when object creation is expensive; reduces GC pressure Can add complexity; must ensure objects are properly reset before reuse Database connections, thread pools, network socket handling
Dependency Injection Supplies an object’s dependencies from the outside rather than creating them internally Constructor, setter, or interface injection; managed by frameworks or containers Increases testability; promotes loose coupling; improves modularity Requires more setup; may be overkill for small projects Spring Framework, .NET Core services, plugin architectures
Key Differences Object creation control (Factory, Abstract Factory, Builder, Prototype) vs instance control (Singleton) vs resource sharing (Flyweight, Object Pool) vs dependency provision (Dependency Injection) Varies: factories hide concrete classes, builder handles step-by-step construction, singleton ensures one instance, flyweight shares state, prototype clones, pool reuses objects, DI injects dependencies Choose based on whether the goal is to simplify creation, control instance count, optimize resources, or decouple dependencies Trade-offs between simplicity, flexibility, and performance; overuse can lead to unnecessary complexity

References

Previous: Consumer-Driven Contract Testing

Next: Abstract Factory Design Pattern Without the Confusion

Home: Design Pattern Evangelist Blog