GoF Design Patterns: A Brief Overview

Overview

Coming from a non-CS background, I never learned about design patterns. Over the years, as a research software developer during my Ph.D. and postdoc, it became increasingly important for me to understand their significance. When writing a large codebases that is expected to evolve over time and intended for widespread use, choosing the right design pattern can significantly impact your code’s future (and mental sanity).

My first introduction to the subject was through the incredibly creative refactoring.guru website by Alexander Shvets. Subsequently, I took an online course in Design Patterns, which covered most of the original GoF patterns and more. I also frequently referred to the classic Gang of Four (GoF) book on the subject.

However, I found myself wanting a quick cheat sheet for these patterns, since I do not remember the details when I need it in my day-to-day. Hence, I’ve created this blog to summarize these patterns through a simplified UML class diagrams. Ie’s not meant to be comprehensive, as there are many websites dedicated to the subject. Instead, it’s a simple and visual reference for those who, like me, prefer to have a quick overview at hand.

What is a design pattern?

As Klaus Iglberger puts it, a design pattern has a name and carries an intent. Each design pattern aims at reducing dependencies within different components of your code and providing a certain level of abstraction.

Design patterns can be divided into three main categories: creational, structural, and behavioral. The creational design patterns are concerned with providing various mechanisms to create objects. The structural design patterns deal with how classes and objects can be composed to form larger structures. The behavioral design patterns focus on how objects communicate and collaborate with each other to achieve specific tasks.

Creational   Structural   Behavioral
Singleton   Adapter   Command
Factory Method   Decorator   Strategy
Abstract Factory   Proxy   Observer
Builder   Composite   Mediator
Prototype   Bridge   State
    Flyweight   Iterator
        Chain of Responsibility
        Memento
        Template Method
        Visitor

Below I provide a brief summary of each design pattern and a simplified UML diagram. My goal is to provide a brief summary of each of these patterns, along with an example for where it may be used in a typical research software. More patterns will be added soon.

Singleton

Ensures that a class has only one instance and provides a global point of access to that instance.

classDiagram
    class Singleton {
        - instance: Singleton
        - Singleton()
        + getInstance(): Singleton
    }

Factory Method

Defines an interface for creating an object, but allows subclasses to alter the type of objects that will be created.

classDiagram
    direction LR
    class Creator {
        <<abstract>>
        + factoryMethod(): Product*
        + someOperation()
    }
    note for Creator "unique_ptr&lt;Product&gt; p = factoryMethod() \n p->doStuff()"
    class ConcreteCreator {
        + factoryMethod(): Product
    }
    note for ConcreteCreator "return make_unique&lt;ConcreteProduct&gt;()"
    class Product {
        <<interface>>
        + doStuff()
    }
    class ConcreteProduct {
        + doStuff()
    }


    Creator <|-- ConcreteCreator
    ConcreteCreator ..> ConcreteProduct : creates

    Product <|.. ConcreteProduct
    Creator ..> Product : uses

Further Exploration




    Enjoy Reading This Article?

    Here are some more articles you might like to read next:

  • Exploring Type Erasure as a Design Pattern: A Generic Materials Solver
  • Exploring Policy-Based Design: A Customizable Message Logger in C++
  • Just-In-Time Compiled CUDA Kernel
  • C++ Template Basics
  • GPU Practice Codes