Design Patterns

Your simplified, one-stop guide to all software engineering design patterns

Gautham Dinesh
5 min readMar 3, 2024
Photo by Ludde Lorentz on Unsplash

Factory

  • Replaces direct construction calls of objects with a factory method.
  • Use an interface to abstract the implementation of the concrete class

Abstract Factory

  • Extend the factory pattern into a family of different abstract methods

Builder

  • Construct complex objects step by step including the necessary components.
  • Don’t bloat a constructor with the components as parameters but instead add builder functions that accumulate and manifest when you finally build.
  • You can also create a Director class that supports different configurations of an object using the same Builder Object

Prototype

  • Uses to create an exact copy of an object and delegates the task to the object being cloned.
  • There is a common interface for all classes that support cloning.

Singleton

  • A class only has a single instance but provides a global access point to itself.
  • Utilizes a private constructor with a static creation method to get the instance of this object.

Adapter

  • Allows objects with incompatible interfaces to collaborate.
  • Converts the interface of one object so that the other can understand it. Sometimes it goes both ways.
  • Extend the functionality of your class by creating an adapter for the interface it needs to work with

Bridge

  • Split a set of closely related classes into two hierarchies — abstraction and implementation. Do this by extracting one of the dimensions into a separate class hierarchy.

Abstraction → GUI
Implementation → OS

  • You can use the abstraction to control the implementation. Like creating a remote control class that takes in a device in the constructor. The remote control class can take any device that implements the Device interface.

Composite

  • Compose objects into tree-like structures and you can work with the whole structure as though it is one object.

Decorator

  • Allows you to attach new behaviors to objects by placing these objects inside special wrapper objects that contain the behaviors. Similar to wrapping in layers of clothing.
  • Do this by extending the base class as many times as you need to.

Facade

  • It provides a simple interface to a complex subsystem with lots of moving parts.
  • Useful in making your code work with another framework, the facade class encapsulates the functionality of your code.

Flyweight

  • Fit more objects into RAM by sharing common parts with multiple objects.
  • Separate the intrinsic and extrinsic parts of an object so that the intrinsic parts can be reused. These features will be created once and can be used for all instances of the object.

Proxy

  • Provides a placeholder for another object so that you can control access, or perform something in the middle.

Chain of Responsibility

  • Allows you to pass a request along a chain of handlers, deciding whether to pass it on or process it at each step.

Command

  • Turns a request into an object that contains all the information about the request.
  • Useful when you to queue operations, or implement reversible operations.
  • This lets you abstract many types of requests which you can then execute using the command pattern under one invoker.

Iterator

  • Allows you to traverse elements of a collection without exposing the underlying representation
  • You can create different iterator implementations for a data structure, each with its states.

Mediator

  • Reduces the chaotic dependencies between objects. Forces the objects to communicate via a mediator object.
  • The mediator controls all the functions of the components rather than letting them interact with each other.

Memento

  • Save and restore the previous state of an application without revealing implementation details.
  • Relies on the originator class creating snapshot states. The originator class can also restore these snapshot states.
  • The memento is a value object that acts as a snapshot of the originator class. It is immutable.
  • The caretaker knows the when and why of the originator’s state and when to restore it. The caretaker stores the mementos in a stack.

Observer

  • Observer is used to notify multiple objects about events that they have subscribed to.
  • The object that the subscribers rely on is called the publisher. The publisher has a function to add subscribers and remove subscribers.
  • Whenever there is change in the publisher that subscribers need to be notified about, the publisher calls a notify method which invokes an update in the subscribers.

State

  • Allows an object to change its behavior based on its current state. A new state object is created for each possible state of an object and all its behavior is extracted into these classes.
  • When an action causes an object’s state to change, the state attribute of the object is set to the specific state object.
  • Actions invoked in this state will be called for that state object. This allows all the behavior in that state to be encapsulated in the object.

Strategy

  • This is used when there are a lot of different ways to accomplish one task. These strategies can be thought of as algorithms to execute one task that can be defined by a common interface.
  • Each strategy accomplishes this task differently and which strategy to use is decided by the context of the class using it.

Template Method

  • Used when you have a series of steps that are performed in different ways by different classes.
  • You can have an abstract class with some default implementation and concrete classes that override the behavior that you need for the specific subclass.

Visitor

  • Use this when you need to operate on all the elements of a complex object structure. If you are going down the object structure tree and need to perform a different action based on the element, then use this pattern.
  • You need a visitor interface with a set of methods, one for each type of class that the method will be used for. The class that the visitor will apply to will have an accept method that takes in a visitor and calls the appropriate visitor method.

For a more in-depth explanation and examples, visit Refactoring Guru. Most of the information in this post comes from there.

--

--