Inspired by the title. (generated by Midjourney)

Introduction

The more you are in software engineering, the more you realize that similar problems are repeated all the time. Moreover, those similar sets of issues are often solved using similar approaches.

That’s where design patterns come in handy. A design pattern is a repeatable solution to a commonly occurring software problem. You can consider it as a “blueprint.” It is not a finished design; it’s more like a template to solve a specific problem that can be used in many different scenarios.

Have a Design Pattern to Share?
If you have anything to add, just email me at me@volkan.io, and I will update this page.

Design patterns can speed up the development process by providing tried and tested paradigms. Using design patterns creates a common language. It makes the code more readable and prevents subtle issues that might become visible much later. It’ll be much harder to modify and refactor the code.

We can split design patterns into three categories:

  • Creational design patterns,
  • Structural design patterns,
  • And behavioral design pattern.

This article summarizes the most commonly used design patterns, with links that discuss each pattern more deeply.

So, without further ado, let’s dig in.

Creational Design Patterns

  • Abstract Factory: Create instances of several kinds of objects.
  • Builder: You have a common source of truth, and you want different representations of it.
  • Factory Method: A (mostly) static method to let a class defer the instantiation to subclasses.
  • Object Pool: Avoid expensive object initialization by maintaining a pool of reusable objects.
  • Prototype: A fully initialized instance that can be cloned elsewhere.
  • Singleton: A class that only has a single instance.

Structural Design Patterns

  • Adapter: Convert an interface into another interface that the client expects.
  • Bridge: Segregate interfaces from their implementations.
  • Composite: A glorified tree structure of objects.
  • Decorator: Monkey-patch additional responsibilities to an object.
  • Façade: There’s a mess behind the doors, but the building looks beautiful.
  • Flyweight: Share as much common data as possible to reduce the memory footprints of instantiated objects.
  • Proxy: An object acting on behalf of another object.

Behavioral Design Patterns

  • Chain of Responsibility: A way to pass the request between a pipeline of middlewares.
  • Command-Query Separation Principle: Things that modify state and things that query state should be isolated.
  • Command: Encapsulate a request and its parameters and context to be run later.
  • Iterator: Access a list of items sequentially without exposing their underlying representations.
  • Mediator: The best analogy is planes talking to the control tower (the mediator) instead of talking to each other, thus reducing exponentially-increasing communication overhead.
  • Memento: Capture an object’s internal state so that it can be re-initialized later, faster.
  • Null Object: Provide a helpful default value of an object. The go programming language leaves and breathes by this.
  • Observer: When one object changes state, all of the interested objects get notified.
  • State: A state machine; the object’s behavior changes (as if its type has changed) when its state changes.
  • Strategy: Define a family of algorithms and make them interchangeable.
  • Template Method: Delegate how the method is implemented to the subclass of an object.
  • Visitor: Represent an operation to be performed on the elements of a graph of objects.

Summary

One thing to keep in mind is that design patterns are just guidelines. They are rules that are set in stone to follow religiously. So the more you use them, the more you’ll realize when it makes to deviate from them.

In addition, not every problem has an exactly matching design pattern. Similarly, not every situation needs to be solved with a design pattern. When in doubt, keep things simple.

Design patterns are what you’d call “guidelines” than actual “rules.”

One last thing: People, especially when learning design patterns for the first time, don’t consider the tradeoffs of using a certain pattern. Each design pattern comes with its benefits and liabilities. And it’s up to you as the software engineer to use your experience and judgement to decide what to use when.

That being said, that’s all there is about common software design patterns.

Until next time… May the source be with you 🦄.