Creational Patterns  «Prev  Next»
Lesson 2What is a creational pattern?
Objective Define creational patterns.

Define Creational Design Patterns

As a software architect, using creational design patterns in place of direct instantiation with constructors can provide you with significant advantages. Direct instantiation with constructors, while straightforward and simple, often leads to tight coupling and a lack of flexibility. Creational design patterns can overcome these limitations and enhance the overall structure and efficiency of your code. Here are some key reasons to use creational design patterns:
  1. Flexibility in Object Creation: Creational design patterns abstract the instantiation process by delegating it to special factory methods or classes. This abstraction allows changing the concrete type of the object being created without altering the code that uses these objects.
  2. Code Reusability and Scalability: With creational patterns, the code is not hardwired to the application, thereby making it easier to manage, more scalable, and more reusable. This is crucial in a large codebase where the instantiation of an object may need to be used across different modules.
  3. Reduced Complexity: Creational design patterns simplify the object creation process, especially when creating complex objects. Patterns like the Builder or the Abstract Factory can break down the creation process into a series of steps or provide an interface to create families of related objects, respectively.
  4. Control Over Object Creation: Creational design patterns can provide finer control over the object creation process. For instance, Singleton pattern ensures only a single instance of a class exists, or the Prototype pattern allows creating new objects by cloning existing ones.
  5. Encapsulation of Code: These patterns encapsulate the code that needs to know about which classes need to be instantiated and hide it from the rest of the system. This encapsulation of responsibilities and processes aids in maintaining a well-structured and modular codebase.
  6. Decoupling: Creational design patterns can help decouple the client code from concrete classes, reducing the dependencies within the system and improving its resilience to change.

In summary, while using constructors for object creation can be the most straightforward approach, leveraging creational design patterns offers you far more benefits, particularly as your codebase grows in size and complexity. These patterns can make your code more robust, flexible, maintainable, and easier to understand, which are critical factors in successful software architecture.

Alternate Method for creating Objects

Creational patterns involve the construction of new objects. However, they rarely use constructors directly. Rather, a creational pattern often hides the constructors in the classes being created, and provides alternate methods to return instances of the desired class. The most common reason for using a creational pattern is that you need to change the class that is instantiated to fit the situation. Clearly, a constructor in a single class is an inadequate method to return instances of possibly different classes. Almost always the objects returned are instances of some common superclass. Class creational patterns use inheritance to vary the object being created. Object creational patterns generally delegate the actual construction to a different object that is responsible for deciding which class is required and invoking the necessary constructor.
Creational design patterns are design patterns that deal with object creation mechanisms, trying to create objects in a manner suitable to the situation. The basic form of object creation could result in design problems or added complexity to the design. Creational design patterns solve this problem by somehow controlling this object creation. Creational design patterns are composed of two dominant ideas. One is encapsulating knowledge about which concrete classes the system use. Another is hiding how instances of these concrete classes are created and combined.

Creational Patterns

  1. Deal with one of the most commonly performed tasks in an OO application, the creation of objects.
  2. Support a uniform, simple, and controlled mechanism to create objects.
  3. Allow the encapsulation of the details about what classes are instantiated and how these instances are created.
  4. Encourage the use of interfaces, which reduces coupling.

Creational Design Patterns Application

The utilization of creational design patterns, as opposed to direct instantiation via constructors, offers several advantages in software development. These design patterns serve as effective mechanisms for object creation, lending greater flexibility, reusability, and maintainability to your codebase. By decoupling the process of object instantiation from the client code, creational design patterns foster adherence to the SOLID principles of object-oriented programming, particularly the Dependency Inversion Principle, thereby enhancing modularity and testability.

Advantages of Creational Patterns

  1. Encapsulation of Construction Logic: By centralizing object creation logic, these patterns keep the codebase DRY (Don't Repeat Yourself), making it easier to manage and modify.
  2. Decoupling: Creational patterns abstract the instantiation process, minimizing the dependencies between objects and allowing them to be more modular.
  3. Single Responsibility Principle: Object creation logic is isolated in a separate class or method, thereby adhering to the Single Responsibility Principle.
  4. Code Reusability: The encapsulated object creation logic can be reused across different parts of the application, promoting code reusability.
  5. Testability: Since creational patterns allow for dependency injection, they facilitate unit testing by making it straightforward to substitute real classes with mock objects.
Example: Singleton Pattern in C++
The Singleton pattern ensures that a class has only one instance and provides a global point to access it. Below is an example implementation of the Singleton pattern in C++:
 
#include <iostream>
#include <memory>

class Singleton
{
private:
    static std::unique_ptr<Singleton> instance;
    Singleton() { std::cout << "Singleton created\n"; }  // Private constructor

public:
    // Deleted copy constructors and assignment operators
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

    static Singleton& getInstance()
    {
        if (instance == nullptr)
        {
            instance = std::unique_ptr<Singleton>(new Singleton);
        }
        return *instance;
    }

    void showMessage()
    {
        std::cout << "Singleton instance\n";
    }
};

// Initialize the static member
std::unique_ptr<Singleton> Singleton::instance = nullptr;

int main()
{
    // Fetch the Singleton instance and use it
    Singleton& s1 = Singleton::getInstance();
    s1.showMessage();

    // Another reference to the same Singleton instance
    Singleton& s2 = Singleton::getInstance();
    s2.showMessage();

    return 0;
}

In this example, the `getInstance()` method ensures that only one instance of the `Singleton` class is created. The use of `std::unique_ptr` ensures that the instance is properly deleted when the application terminates, providing basic memory management for the Singleton object. In summary, the judicious application of creational design patterns offers more than just a sophisticated alternative to direct instantiation; it is a manifestation of mature design and architectural prudence. By embodying the best practices of object-oriented programming, creational patterns proffer an extensible, maintainable, and testable codebase, thereby contributing to the software's overall quality and longevity.

Factory Method When a client object does not know which class to instantiate, it can make use of the factory method to create an instance of an appropriate class from a class hierarchy or a family of related classes. The factory method may be designed as part of the client itself or in a separate class. The class that contains the factory method or any of its subclasses decides on which class to select and how to instantiate it.
Singleton Provides a controlled object creation mechanism to ensure that only one instance of a given class exists.
Abstract FactoryAllows the creation of an instance of a class from a suite of related classes without having a client object to specify the actual concrete class to be instantiated.
PrototypeProvides a simpler way of creating an object by cloning it from an existing (prototype) object.
BuilderAllows the creation of a complex object by providing the information on only its type and content, keeping the details of the object creation transparent to the client. This allows the same construction process to produce different representations of the object.