Creational patterns

2 min read

Creational patterns deal with object creation mechanisms, trying to create objects in a manner suitable to the situation.

Singleton

Intent: ensure that a class has only one instance, and provide a global point of access to that instance.

Use cases: managing shared resources like configuration managers, logging services, database connection pools, or hardware interface access.

C# implementation considerations: thread safety is a key concern when you implement a Singleton in a multi-threaded environment. Lazy<T> is a simple way to get thread-safe lazy initialization.

In the example, the Lazy<T> field holds the one instance. The private constructor stops anyone else from creating one. The Instance property is the global access point.

C#
// Thread-safe Singleton using Lazy<T>public sealed class ConfigurationManager{    private static readonly Lazy<ConfigurationManager> _lazyInstance =        new Lazy<ConfigurationManager>(() => new ConfigurationManager());     // Private constructor to prevent external instantiation    private ConfigurationManager()    {        // Load configuration settings here        Console.WriteLine("ConfigurationManager instance created.");    }     public static ConfigurationManager Instance => _lazyInstance.Value;     public string GetSetting(string key) { /* Retrieve setting */ return $"Value for {key}"; }}

Factory Method

Intent: define an interface (or abstract class) for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

Use cases: when a class cannot anticipate the class of objects it must create, or when a class wants its subclasses to specify the objects it creates. It’s useful for decoupling client code from concrete product classes.

Abstract Factory

Intent: provide an interface for creating families of related or dependent objects without specifying their concrete classes.

Use cases: when a system needs to be independent of how its products are created, composed and represented, and when the system needs to be configured with one of multiple families of products.

Builder

Intent: separate the construction of a complex object from its representation, so that the same construction process can create different representations.

Use cases: when the algorithm for creating a complex object should be independent of the parts that make up the object and how they’re assembled. It’s useful when construction involves multiple steps or optional configurations.

The other two categories are structuralStructural patternsFour patterns for composing classes and objects into larger structures.Opens in a new tab and behavioralBehavioral patternsFour patterns for how objects interact and share out responsibilities.Opens in a new tab.


Sources