Quick View of Design Patterns from Gang of Four (GoF) Book

Shadman Jamil
9 min readFeb 22, 2022

--

The best designers use many design patterns

Design Pattern

Design patterns are general, reusable solutions to solve common problems in software design. Each pattern is like a blueprint that you can customize to solve a specific problem in your code.

Categories of Design Patterns

In GoF (Gang of Four) we have 3 categories of Design Patterns

  1. Creational Patterns
  2. Structural Patterns
  3. Behavioral Patterns

1. Creational Patterns

These patterns provide a way to create objects while hiding the creation logic rather than instantiating objects. ex: encapsulation.

In simple words, these patterns provide various object creation mechanisms, which increase flexibility and reuse of existing code.

  • Singleton Pattern [A class of which only a single instance can exist]

This design pattern lets you ensure that a class has only one instance while providing a global access point to this instance. It solves two problems at a time, violating the Single Responsibility Principle.

Singleton’s implementation has two things in common:

  • Make the default constructor private, to prevent other objects from using the new operator with the Singleton class.
  • Create a static creation method that acts as a constructor. That method will call the private constructor to create an object and save it in a static field. As a result, all following calls to this method return the cached object.
  • Prototype Pattern [A fully initialized instance to be copied or cloned]

This pattern lets you copy existing objects without making your code dependent on their classes.

The Prototype pattern delegates the cloning process to the actual objects that are being cloned. The pattern declares a common interface for all objects that support cloning. This interface lets you clone an object without coupling your code to the class of that object.

The implementation of the clone the method is very similar in all classes. The method creates an object of the current class and carries over all the field values of the old object into the new one. You can even copy private fields because most programming languages let objects access the private fields of other objects that belong to the same class.

This pattern is used when the creation of an object directly is costly. ex: An object is to be created after a costly database operation. We can cache the object, return its clone on the next request, and update the database as and when needed thus reducing database calls.

  • Builder Pattern [Separates object construction from its representation]

This pattern lets you construct complex objects step by step. This pattern allows you to produce different types and representations of an object using the same construction code.

The Builder pattern suggests that you extract the object construction code out of its class and move it to separate objects called builders.

  • Factory Method Pattern [Creates an instance of several derived classes]

This pattern deals with the problem of creating objects without having to specify the exact class of the object that will be created. This is done by creating objects by calling a factory method.

It provides an interface for creating objects in a base class but allows sub-classes to alter the type of objects that will be created.

Either specified in an interface and implemented by sub-classes or implemented in a base class and optionally overridden by derived classes, rather than by calling a constructor.

  • Abstract Factory Pattern [Creates an instance of several families of classes]

This pattern lets you produce families of related objects without specifying their concrete classes.

It works around a super-factory which creates other factories. This factory is also called a factory of factories.

2. Structural Patterns

Structural patterns are concerned with how classes and objects are composed to form larger structures. Structural class patterns use inheritance to compose interfaces or implementations

  • Composite Pattern [A tree structure of simple and composite objects]

This pattern is used when we need to treat a group of objects in a similar way as a single object. Composite pattern composes objects in terms of a tree structure to represent part as well as a whole hierarchy.

In simple words, this pattern creates a class that contains a group of its objects. This class provides ways to modify its group of the same objects.

  • Adapter Pattern [Match interfaces of different classes]

This design pattern works as a bridge between two incompatible interfaces. This type of design pattern comes under a structural pattern as this pattern combines the capability of two independent interfaces.

You can create an adapter. This is a special object that converts the interface of one object so that another object can understand it.

An adapter wraps one of the objects to hide the complexity of conversion happening behind the scenes. The wrapped object isn’t even aware of the adapter.

  • Bridge Pattern [Separates an object’s interface from its implementation]

This design pattern lets you split a large class or a set of closely related classes into two separate hierarchies; abstraction and implementation, which can be developed independently of each other.

This pattern is used when we need to decouple an abstraction from its implementation so that the two can vary independently. This type of design pattern comes under structural pattern as this pattern decouples the implementation class and abstract class by providing a bridge structure between them.

  • Decorator Pattern [Add responsibilities to objects dynamically]

This design pattern allows a user to add new functionality to an existing object without altering its structure. This type of design pattern comes under a structural pattern as this pattern acts as a wrapper to the existing class.

This pattern creates a decorator class that wraps the original class and provides additional functionality keeping the class methods signature intact.

In simple words, this pattern lets you attach new behaviors to objects by placing these objects inside special wrapper objects that contain the behaviors.

  • Facade Pattern [A single class that represents an entire subsystem]

This pattern provides a simplified interface to a library, a framework, or any other complex set of classes.

It hides the complexities of the system and provides an interface to the client using which the client can access the system. This type of design pattern comes under a structural pattern as this pattern adds an interface to the existing system to hide its complexities.

  • Proxy Pattern [An object representing another object]

This design pattern lets you provide a substitute or placeholder for another object. A proxy controls access to the original object, allowing you to perform something either before or after the request gets through to the original object.

In this pattern, a class represents the functionality of another class. This type of design pattern comes under a structural pattern.

  • Flyweight Pattern [A fine-grained instance used for efficient sharing]

The flyweight pattern is primarily used to reduce the number of objects created decrease memory footprint and increase performance. This type of design pattern comes under structural pattern as this pattern provides ways to decrease object count thus improving the object structure of the application.

In simple words, this pattern lets you fit more objects into the available amount of RAM by sharing common parts of the state between multiple objects instead of keeping all of the data in each object.

This pattern also suggests that you stop storing the extrinsic state inside the object. Instead, you should pass this state to specific methods which rely on it. Only the intrinsic state stays within the object, letting you reuse it in different contexts. As a result, you’d need fewer of these objects since they only differ in the intrinsic state, which has much fewer variations than the extrinsic.

3. Behavioral Patterns

In these design patterns, identify common communication patterns between objects and realize these patterns. These patterns are also concerned with algorithms and the assignment of responsibilities between objects.

  • Iterator Pattern [Sequentially access the elements of a collection]

This pattern lets you traverse elements of a collection without exposing its underlying representation. ex: list, stack, tree, etc.

The main idea of the Iterator pattern is to extract the traversal behavior of a collection into a separate object called an iterator.

  • State Pattern [Alter an object’s behavior when its state changes]

In this pattern, we create objects that represent various states and a context object whose behavior varies as its state object changes. This type of design pattern comes under a behavior pattern.

  • Command Pattern [Encapsulate a command request as an object]

This pattern is a data-driven design pattern and falls under the behavioral pattern category. A request is wrapped under an object as a command and passed to the invoker object.

Invoker object looks for the appropriate object that can handle this command and passes the command to the corresponding object that executes the command.

  • Chain of Responsibility Pattern [A way of passing a request between a chain of objects]

As the name suggests, the chain of responsibility pattern creates a chain of receiver objects for a request. This pattern decouples the sender and receiver of a request based on the type of request.

Upon receiving a request, each handler decides either to process the request or to pass it to the next handler in the chain.

In this pattern, normally each receiver contains a reference to another receiver. If one object cannot handle the request then it passes the same to the next receiver and so on.

  • Template Pattern [Defer the exact steps of an algorithm to a subclass]

In this design pattern, an abstract class exposes defined way(s)/template(s) to execute its methods. Its subclasses can override the method implementation as per need but the invocation is to be in the same way as defined by an abstract class.

defines the skeleton of an algorithm in the parent class but lets child classes override specific steps of the algorithm without changing its structure.

  • Observer Pattern [A way of notifying change to a number of classes]

This design pattern is used when there is a one-to-many relationship between objects such as if one object is modified, its dependent objects are to be notified automatically.

In simple words lets you define a subscription mechanism to notify multiple objects about any events that happen to the object they are observing.

  • Strategy Pattern [Encapsulates an algorithm inside a class]

In this pattern, a class behavior or its algorithm can be changed at run time.

We create objects that represent various strategies and a context object whose behavior varies as per its strategy object.

The strategy object changes the executing algorithm of the context object.

Cheers!

--

--

Shadman Jamil

Tech Savvy, Software Architect, Mentor, and Entrepreneur