Creational Patterns

Overview

Creational patterns represent how objects or groups of related objects are initialized. They help to make the system independent of how the objects are created and composed.

Creational patterns encapsulate the information about concrete classes used in a system and hide initialization details. Instead of the classes themselves, the system relies on their interfaces.

Materials

🏭 Factory Method

Factory Method provides an interface for object creation via a superclass that delegates initialization logic to its child classes.

Class Diagram

Factory Method Class Diagram

Structure

  • Product describes an object’s interface returned from the Creator’s factory method and subclasses
  • ConcreteProduct is a particular implementation of the Product interface, which will differ per Creator implementation
  • Creator is a class containing a factory method and returning contextual Product implementations by initiating the new objects
  • ConcreteCreator is a class that extends the Creator class and overrides (implements) its factory method

When to use

  • Provide a way to extend a system with the custom component implementation.
  • Reuse the logic for new object creation.
  • When there is a generic processing class, the client doesn’t know what exact objects it needs and decides it in a runtime.

Implementation

Notes

  • The Creator class can initialize the Product objects and contain a logic that uses them.
  • The Creator class can provide a default implementation in the createProduct() method instead of declaring it as blank abstract.
  • The Creator class can return the Product object from various sources (cache, third-party) instead basic creation of the new instances.

Examples

🏘 Abstract Factory

Abstract Factory allows creating the group of related objects without specifying their concrete classes. This factory produces a family of products with a particular variant.

The example below demonstrates UI elements (products) family presented via platform-specific variants:

Variant / ProductInputCheckboxRadioButton
BrowserInputTagCheckboxTagRadioTag
MacOSUIInputUICheckboxUIRadio
WindowsWinInputWinCheckboxWinRadioButton

Class Diagram

Abstract Factory Class Diagram

Structure

  • Product interface declares a common product structure
  • ConcreteProduct implements different variants of the abstract Product
  • AbstractFactory interface declares creation methods per each abstract Product
  • ConcreteFactory implements abstract factory methods returning ConcreteProduct objects
  • Client uses only abstract Product and AbstractFactory interfaces to work with the concrete products

When to use

  • When a system shouldn’t depend on the included internal objects.
  • When a group of related objects included in a particular module should be used together.
  • A system needs to be configured by a group of related objects.
  • A module needs to work with different variants of the same group of objects.
  • You need to provide a library of components specified by their interfaces, not the actual implementation.
  • To evolve the architecture implemented with Factory Methods pattern.

Implementation

Notes

  • Client class must use the interfaces provided by abstract classes, not by their concrete implementation.
  • ConcreteFactory can be implemented as a Singleton.

Examples

πŸ‘· Builder

Builder lets you construct complex objects step by step. It allows to create different representations of the object using a construction code instructions.

Class Diagram

Builder Class Diagram

Structure

  • Builder interface declares Product construction steps common for all builders
  • ConcreteBuilder implements object construction steps
  • Product is a resulting object created by ConcreteBuilder
  • Director produces a list of building operations in a particular order to create a Product with a specified Builder implementation

When to use

  • When a class provides a lot of configurations that need to be passed via its constructor.
  • To create a different concrete object representation of some product (class).
  • The complex object creation process is independent of object parts and the relation between them.

Implementation

Notes

  • The Client (or system code) is not receiving the built object directly from the Director. Instead, once the Director has finished building operations, the Client should take the result object from the ConcreteBuilder.

Examples

🧬 Prototype

Prototype pattern allows to clone existing objects without dependencies on their classes. This pattern delegates the cloning process to the actual object being cloned.

To make an object a prototype, it has to provide the clone() method that creates an object of the current class and copies the state (methods, public/protected/private fields) to the newly created instance.

Class Diagram

Prototype Class Diagram

Structure

  • Prototype interface declares a cloning method
  • ConcretePrototype implements a cloning method from Prototype interface where coping current’s object state in a new object instance and dealing with the corresponding edge cases
  • Client makes a copy of any object that conforms Prototype interface

When to use

  • When the code shouldn’t depend on the concrete class of the cloned object.
  • To reduce the number of subclasses that only differ in the way they initialize objects.
  • To avoid building complex inheritance chains and factories for making various product variations.
  • When the object can have a limited number of states, it might be simpler to create a corresponding amount of prototypes and clone them instead of reproducing the object state from scratch.

Implementation

Notes

  • Prototype’s clone() implementation can be tricky if the object has circular dependencies or non-primitive attributes (all the referenced objects need to be cloned as well).

Examples

πŸ₯‡ Singleton

Singleton pattern allows to create a single instance of the class and returns it for all future calls.

Another implementation called Multiton allows to manage a map of instances identified by their unique keys.

Class Diagram

Original Singleton class diagram:

Singleton Class Diagram

Modified Multiton diagram:

Multiton Class Diagram

Structure

  • Singleton class, declaring a static method that returns the same instance per every invocation
  • Client accessing Singleton class to retrieve the shared instance

When to use

  • The object represents a single shared resource that has to be available everywhere (for example, a database connection or a file descriptor).
  • To share the objects across the system safely as opposed to global variables.

Implementation

Notes

  • Singleton instance and getInstance() must be implemented as static class fields.
  • Singleton constructor must be declared as private to prevent the creation of new instances outside the class.
  • In multithread environments, the processes should be synchronized to avoid the parallel creation of the singleton instance.
  • Spawning a lot of singletons might affect the system design with the overused global data.

Examples

πŸŠβ€β™‚οΈ Object Pool

The Object Pool pattern is designed to reuse the already initiated objects rather than allocating and destroying them on demand. It’s most efficient when object initialization is time-consuming, and the existing allocated objects can be reused (for example, database connection).

Object Pool creates a set of objects used by the client logic for a relatively short period of time. When a client needs the object, it takes that from the pool. After the object is no longer needed, it is returned to the pool for future usage by other system components. If the request object does not exist in the pool, it should be initialized.

Class Diagram

Object Pool Class Diagram

Structure

  • ObjectPool is a class that manages the initialized objects
  • ConcreteProduct is the class which instances will be stored on the pool
  • Client is a system logic using objects from the pool

When to use

  • When the same objects need to be reused across the app for the short time operations.
  • When the frequently reused object’s initialization is time expensive.
  • For objects that store connection (database, sockets) or large objects (graphics, binaries).

Implementation

Notes

  • Object Pool is generally implemented via a Singleton to make the stored instances reusable across the whole app.
  • Object Pool can have an additional object management logic such as time-to-live and the objects storage limitation.
  • Make sure that the pollable objects can be reused and the application doesn’t mutate them during the usage.
  • Once the Client releases the object, it has to finish using it to prevent parallel usage once another service takes the object.

Examples