Software Design Patterns: Creational, Structural, Behavioral

Creational Patterns

Creator patterns streamline the process of creating instances, helping a system to be independent of how its objects are created, composed, and represented.

Factory

Provides an interface for creating an object without revealing the object’s actual class. Motivation: Uses abstract classes/interfaces to define and maintain relations between objects and sometimes creates them. Advantages: Eliminates the need to link our code with specific classes. Disadvantages: Customers may have to inherit from the Creator class to create a specific Product.

Abstract Factory

Provides an interface for creating families of related or dependent objects without specifying their concrete classes. We use it when the system should be independent of how its products are created, composed, and represented, or when it should be configured with one of multiple families of products. Also, when you want to reveal only the interface, and not the implementation, of a class library of products.

Advantages:

  • Isolates concrete classes
  • Makes exchanging product families easy
  • Promotes consistency among products

Disadvantages:

  • Supporting new kinds of products is difficult

Proxy

Provides an agent or substitute for another object to control access to it. Delays the entire cost of its creation and initialization until it is necessary to use it. For example, in the context of retrieving multiple objects from a file or handling images in a word processor. There are several types:

  • Remote: Provides a local representative of an object located in another address space
  • Virtual: Creates expensive objects by order
  • Protection: Controls access to the original object

Singleton

Ensures that a class has only one instance and provides a global point of access to it. A global variable makes an object accessible but does not keep you from instantiating multiple objects. So, a better solution is to make the class itself responsible for keeping track of its unique instance. The class ensures that no other instance can be created (by intercepting requests to create new objects).

Advantages:

  • Controlled access to the sole instance
  • Reduced name space, avoids polluting the name space with global variables that store sole instances

Builder

Separates the construction of a complex object from its representation, so the same process of construction may create different representations of the object. Suppose we want to build an RTF editor that can convert text to different formats. The number of formats should not be determined at first. It should be applied when the algorithm to create a complex object should be independent of the parts of that object, how it is composed, and how they are assembled, or when the construction process should allow different representations of the object being constructed.

Advantages:

  • Allows multiple representations of a product
  • Isolates the code of construction and representation
  • Provides better control over the building process

Structural Patterns

Structural patterns are concerned with how classes and objects are combined to form larger structures.

Composite

Used to build complex structures from other simpler structures. We can create composite structures that are made up of other smaller ones. For example, a brick house. The house as such is not made of one piece. If we observe the walls, they are made of small pieces called bricks. Then the set of these bricks creates walls, and a set of walls creates a house. Component: Interface or abstract class which has the minimum operations that will be used, extended by Leaf and Composite. Leaf: Represents the simplest or smallest part of the whole structure. For example, a brick in the house. Composite: Structure made up of other Composites and Leaves, has the add and remove methods which allow us to add objects of type Component. It is usually an Interface or Abstract Class so we can aggregate objects of type Composite or Leaf.

Advantages:

  • Define class hierarchies by primitive and composite objects
  • Easy to add new components

Disadvantages:

  • Hides the types of objects within the composite

Decorator

Assigns additional responsibilities to an object dynamically, providing a flexible alternative to inheritance to extend functionality. It is used a lot in GUI. It should be applied when you want to add individual objects dynamically and transparently, that is, without affecting other objects. Also, when the possibility of eliminating responsibilities is desired.

Advantages:

  • More flexibility than static multiple inheritance
  • Avoids classes loaded with functions at the top of the hierarchy, since they can be added in the decorator

Disadvantages:

  • A decorator and its component aren’t identical
  • Many small objects

Visitor

Allows for new operations to be defined and used on elements of an object structure without changing the classes of the elements on which it operates. Each new operation should be added separately. Package related operations from each class in a separate object (Visitor) and pass it to elements of the abstract syntax tree as it is traversed. When an element accepts a visitor, it sends a request to it that encodes the element’s class.

Facade

Provides a unified interface for a subsystem set of interfaces. Defines a high-level interface that makes the subsystem easier to use. Motivation: Structuring a system into subsystems helps to reduce the complexity. Minimize communication and dependencies between subsystems. One way to do this is to introduce a facade object that provides a single, simplified interface for more general subsystem services. It should be applied when there are many dependencies between clients and classes that implement an abstraction or when we want to split into layers our subsystem.

Advantages:

  • Hides clients from subsystem components, thus reducing the number of objects customers are dealing with and making the subsystem easier to use
  • Doesn’t prevent applications from using subsystem classes if necessary

Disadvantages:

  • New component’s operations should promote towards the interface of the facade

Behavioral Patterns

Consist of algorithms and the assignment of responsibilities to objects. These patterns describe patterns of object’s classes and patterns of communication between these classes and objects. The last one uses inheritance to distribute behavior between classes, whereas the object’s one uses composition to distribute the behavior.

Template Method

Defines the skeleton of an algorithm in an operation, delegating some steps to the subclasses. It allows subclasses to redefine certain steps of an algorithm without changing its structure. Motivation: To have a framework of applications and documents, that the interaction between these classes is always the same and that concrete classes must respond in different ways to the same interaction. It should be applied when you want to implement the parts of an algorithm that don’t change and let the subclasses implement the behavior that may change, or when the repeated behavior of several subclasses should be factorized and located in a common class to avoid duplicate code. Also, control subclass extensions. Advantages: Allows code reuse.

Command

Encapsulates the request in an object, allowing to parameterize clients with different requests, make a queue, or keep a record of requests and be able to undo operations. It is used because sometimes it is necessary to send requests to objects without knowing anything about the requested operation or who is the receiver of the request. Converts the request into an object, which can be saved and sent like any other object.

Advantages:

  • Frees the object invoking the operation from the one that knows how to do it
  • You can assemble orders in a compound order
  • Easy to add new commands

Mediator

Encapsulating the collective behavior in a separate Mediator object avoids these problems. Responsible for controlling and coordinating the interactions of a group of objects. It must be applied when a set of objects communicate in a well-defined but complex way. The resulting independence is not structured and difficult to understand. It also applies when it is difficult to reuse an object since it refers to many other objects which it communicates, or when a behavior that is distributed among several classes should be adaptable without many subclasses.

Advantages:

  • Reduce inheritance
  • Simplify object protocols
  • Abstracts how objects cooperate

Disadvantages:

  • Centralize control

Iterator

Provides a way to access the elements of an aggregate object sequentially without exposing its underlying representation. An aggregate object (like a list) should give us a way to access its elements without exposing its internal structure. We may want to do various things with the components on the list or we need to do more than one tour simultaneously. It must be applied when you want to access the contents of an aggregated object without exposing its internal representation, to allow multiple paths over aggregated objects, or to provide a uniform interface for traversing different aggregated structures.

Advantages:

  • Allows variations in the path of an aggregate
  • Simplifies the interface of the aggregate object
  • You can make more than one course at a time on an aggregate