Skip to content
Sanfor2004
← All articles
Design PatternsDesign PatternsPythonC++ArchitectureSoftware Engineering

Design Patterns Overview (Creational, Structural, and Behavioral Patterns)

By Ahmed (Sanfor) · 12 Sept 2026 · 12 min read
An open sketchbook becomes a workshop, modular bridges, and connected signal stations, illustrating creation, structure, and collaboration.

Design patterns give us names for recurring design decisions: who creates an object, how components fit together, and who decides what happens next. Knowing a name is useful only when you can explain the problem it solves and the cost of adding it.

This is the starting point for my 24-post series: this overview and one article for each of the 23 patterns. The articles are based on my 23 Design Patterns repository, with complete Python and C++20 examples, expected output for each, and practical limitations. Each article pairs a familiar cover illustration with a sketch map of its example’s roles and flow.

What is a design pattern?

A pattern describes a recurring problem, the responsibilities that can solve it, and the consequences of arranging those responsibilities in a particular way. It is a design vocabulary, not a package you install or a requirement to create a fixed number of classes.

For example, choosing a shipping calculation can be a Strategy implemented as a callable. You do not need a deep inheritance hierarchy to express that choice. A Composite, on the other hand, becomes useful when a file and a folder need the same operation even though one folder owns more entries.

The familiar group of 23 comes from Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, often called the Gang of Four or GoF. The publisher’s catalog identifies the book and its pattern chapters. The explanations and runnable examples in this series come from my own repository.

What you need before starting

You should be comfortable reading a small program with functions, classes, constructors, and a few collaborating objects. You do not need to memorize the catalog first.

  • Interfaces and contracts: know what an operation promises to its caller, including errors and lifetime requirements.
  • Encapsulation: understand why a caller should not directly edit another object’s internal state.
  • Composition and delegation: recognize when an object owns or borrows a collaborator and asks it to do part of the work.
  • Inheritance and polymorphism: understand an overridable operation and a call made through a base interface.
  • Ownership and lifetime: in the C++ examples, distinguish a value, a borrowed reference, std::unique_ptr, std::shared_ptr, and std::weak_ptr.
  • Testing: be able to predict output, try a boundary case, and explain what a small example does not test.

The repository’s glossary explains the terms used in each article. You can read the prose without installing anything. Run the first example with Python 3.10 or newer; the C++20 version needs a C++20 compiler, and the repository’s combined build needs CMake 3.20 or newer.

Three categories: what part of the design changes?

The category in each article title answers a practical question. It is the pattern’s purpose, not the name of a programming-language class.

Category Question Typical pressure
Creational patterns How should objects be created or configured? Concrete construction details are spreading through callers.
Structural patterns How should objects and classes fit together? Interfaces, wrappers, or part-whole structures need a clearer boundary.
Behavioral patterns How should work and communication be divided? Algorithms, requests, transitions, or notifications are becoming tangled.

There are five creational, seven structural, and eleven behavioral patterns in this series. A real design can combine patterns from more than one category.

Class scope and object scope

Purpose and scope are different ways of describing a pattern. Class scope emphasizes inheritance relationships and behavior supplied by subclasses. Object scope emphasizes collaborating instances, usually connected through composition or delegation.

Factory Method and Template Method make their extension points especially clear through inheritance. Strategy and Bridge illustrate composition: a context or abstraction keeps a collaborator behind a contract. Adapter has both class-based and object-based forms; the Adapter article uses an object adapter that borrows a sensor.

This distinction helps you ask where change happens. Must someone introduce a subclass, supply a different object, or do both? It does not mean object-scope patterns avoid classes. Their implementations still have types; the flexibility comes from how their objects are connected.

Creational patterns

A furniture workshop assembles matching chairs, tables, and cabinets as one coordinated family.
Abstract Factory: choose the style once, then obtain matching furniture pieces as a related family.

In the Abstract Factory example, those pieces become a button and a panel from the same theme. Other creational patterns address different construction pressures.

Abstract Factory

Abstract Factory (Creational Pattern) — Create compatible families of objects without coupling the client to concrete classes.

Several related objects must vary together. The article explains the participating classes, the implementation, and when that extra structure is unnecessary.

Builder

Builder (Creational Pattern) — Construct a complex object step by step while allowing different final representations.

Construction has meaningful ordered steps. The article explains the participating classes, the implementation, and when that extra structure is unnecessary.

Factory Method

Factory Method (Creational Pattern) — Let subclasses or specialized creators decide which concrete product to instantiate.

A framework supplies the workflow but extensions choose products. The article explains the participating classes, the implementation, and when that extra structure is unnecessary.

Prototype

Prototype (Creational Pattern) — Create new objects by copying an existing configured prototype.

Initialization is expensive or discovered at runtime. The article explains the participating classes, the implementation, and when that extra structure is unnecessary.

Singleton

Singleton (Creational Pattern) — Provide one controlled instance and a global access point—while understanding the coupling it creates.

Exactly one process-wide coordinator is a real invariant. The article explains the participating classes, the implementation, and when that extra structure is unnecessary.

Structural patterns

Shipping boxes contain smaller boxes and individual items in a nested structure.
Composite: a box can contain items or smaller boxes. The file-and-folder example uses the same recursive relationship to calculate a total.

Structural patterns organize connections. A wrapper may translate an interface, add behavior, or control access; those similar shapes have different intentions. Start by naming the boundary you need.

Adapter

Adapter (Structural Pattern) — Translate one interface into another interface the client already understands.

Integrating legacy or third-party code. Read the implementation and its trade-offs before choosing this structure.

Bridge

Bridge (Structural Pattern) — Separate an abstraction from its implementation so both dimensions can vary independently.

Two independent dimensions would otherwise multiply subclasses. Read the implementation and its trade-offs before choosing this structure.

Composite

Composite (Structural Pattern) — Treat individual objects and nested groups through the same component interface.

Data naturally forms a part-whole tree. Read the implementation and its trade-offs before choosing this structure.

Decorator

Decorator (Structural Pattern) — Add responsibilities by wrapping an object with components that share its interface.

Responsibilities must be combined dynamically. Read the implementation and its trade-offs before choosing this structure.

Facade

Facade (Structural Pattern) — Offer a focused entry point to a complex subsystem without removing lower-level access.

Most callers need a small set of common workflows. Read the implementation and its trade-offs before choosing this structure.

Flyweight

Flyweight (Structural Pattern) — Share repeated intrinsic state while keeping context-specific state outside the shared object.

Object count is huge and repeated state dominates memory. Read the implementation and its trade-offs before choosing this structure.

Proxy

Proxy (Structural Pattern) — Stand in for another object to control access, loading, location, or instrumentation.

Lazy loading, remote access, authorization, or caching is transparent to clients. Read the implementation and its trade-offs before choosing this structure.

Behavioral patterns

A notification source sends updates to multiple subscribers.
Observer: one change reaches several interested listeners. The example separates the stock publisher from the displays that subscribe to it.

Behavioral patterns make responsibility explicit: who chooses an algorithm, handles an event, traverses data, coordinates peers, or remembers an earlier state. The important distinction is the collaboration, not the number of classes.

Chain of Responsibility

Chain of Responsibility (Behavioral Pattern) — Pass a request through an ordered chain until a handler processes it or the chain ends.

The receiver is selected dynamically from an ordered pipeline. Follow the article’s example, then try its challenge to explore a boundary the demonstration does not cover.

Command

Command (Behavioral Pattern) — Represent a request as an object so it can be queued, logged, retried, or undone.

Operations need queuing, history, retry, or undo. Follow the article’s example, then try its challenge to explore a boundary the demonstration does not cover.

Interpreter

Interpreter (Behavioral Pattern) — Represent a small grammar as objects that evaluate expressions in a context.

The grammar is small, stable, and evaluated often. Follow the article’s example, then try its challenge to explore a boundary the demonstration does not cover.

Iterator

Iterator (Behavioral Pattern) — Traverse a collection without exposing how that collection stores its elements.

A collection needs multiple traversal strategies. Follow the article’s example, then try its challenge to explore a boundary the demonstration does not cover.

Mediator

Mediator (Behavioral Pattern) — Centralize complex collaboration so peer objects do not depend directly on one another.

Peer-to-peer dependencies have become tangled. Follow the article’s example, then try its challenge to explore a boundary the demonstration does not cover.

Memento

Memento (Behavioral Pattern) — Capture and restore an object’s state without exposing its internal representation.

State snapshots are needed for undo or rollback. Follow the article’s example, then try its challenge to explore a boundary the demonstration does not cover.

Observer

Observer (Behavioral Pattern) — Notify a changing set of subscribers when a subject emits an event or changes state.

One event has multiple independently changing reactions. Follow the article’s example, then try its challenge to explore a boundary the demonstration does not cover.

State

State (Behavioral Pattern) — Change an object’s behavior when its internal state changes by delegating to state objects.

Behavior changes substantially across explicit states. Follow the article’s example, then try its challenge to explore a boundary the demonstration does not cover.

Strategy

Strategy (Behavioral Pattern) — Package interchangeable algorithms behind one interface and choose among them by composition.

Several algorithms solve the same defined task. Follow the article’s example, then try its challenge to explore a boundary the demonstration does not cover.

Template Method

Template Method (Behavioral Pattern) — Define an algorithm’s stable skeleton while allowing selected steps to vary in subclasses.

The workflow order is invariant but selected steps vary. Follow the article’s example, then try its challenge to explore a boundary the demonstration does not cover.

Visitor

Visitor (Behavioral Pattern) — Add operations across a stable set of element types without placing every operation on those elements.

Element types are stable while new operations are frequent. Follow the article’s example, then try its challenge to explore a boundary the demonstration does not cover.

Where would I use these ideas?

The repository examples are small enough to trace. Their application contexts suggest where to investigate a pattern, not proof that the demonstrations are production-ready services.

Situation Patterns to compare Question to settle first
Configuring a request or choosing a service implementation Builder, Factory Method, Abstract Factory Are you assembling options, choosing one product, or coordinating a family?
Connecting an existing library or simplifying a workflow Adapter, Facade Do you need compatibility or a smaller entry point?
Adding optional features or deferring expensive work Decorator, Proxy Are you adding responsibility or controlling access?
Choosing a shipping rule or managing a device lifecycle Strategy, State Is behavior selected as a policy or determined by the current state?
Editing a document with history Command, Memento Must you remember an action, a snapshot, or both?
Updating screens after a change Observer, Mediator Are you broadcasting a change or coordinating specific peers?
Processing a tree Composite, Iterator, Visitor Are you modeling the structure, traversing it, or adding typed operations?

For instance, wrapping a payment library can make its interface easier to use, but it does not make a checkout transaction atomic. The Facade article explicitly keeps that limitation visible. Likewise, a Singleton may have safe initialization while its later mutations still need synchronization.

A practical reading order

If you are new to the subject, follow the repository’s progression rather than trying to memorize the alphabetical catalog:

  1. Strategy, Observer, Factory Method, and Adapter introduce small, visible boundaries.
  2. Decorator, Command, Composite, and State add composition, history, trees, and transitions.
  3. Facade, Builder, Template Method, Bridge, Proxy, Chain of Responsibility, and Mediator broaden the design choices.
  4. Abstract Factory, Prototype, Memento, Iterator, Flyweight, Interpreter, Visitor, and Singleton deserve extra attention to ownership, copying, dispatch, and global state.

For each article, read the problem before the code. Predict the output, trace who owns each object, then change the example using its mini challenge. Compare the simplest alternative with the pattern and explain which change made the extra structure worthwhile.

Run the C++20 examples

Clone the repository and run these commands there, not in the portfolio source:

git clone https://github.com/sanfor2004/23-Design-Patterns.git
cd 23-Design-Patterns
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build build --config Debug
ctest --test-dir build -C Debug --output-on-failure

On Windows, use a Visual Studio developer shell with C++ tools installed. The build guide explains single-pattern targets and compiler choices. Each example has a main.cpp and an expected.txt; the checks compare the demonstration’s output, not every possible behavior of an application using the pattern.

When you do not need a pattern

Keep the simple design when one function, a small value type, or a readable conditional expresses the requirement. Repetition in syntax is not always evidence of the same responsibility. An abstraction chosen before the variation is understood can make unrelated changes depend on one another.

Before introducing a pattern, answer four questions: What is changing? Which caller currently knows too much? What contract will remain stable? What new cost will the pattern introduce? Costs include extra types, indirection, copying, retained memory, difficult lifetimes, and less visible control flow.

The aim of this series is to make those decisions explainable. Use the complete illustrated index above to find a pattern, and return here when two patterns seem similar.

Source and illustration notes

The 23 Design Patterns repository is the source for the C++20 examples and adapted articles. It also contains comparisons, a cheat sheet, and a relationship map.

The overview’s dedicated cover opens a sketchbook onto three connected ideas: a workshop creates components, modular bridges combine them into structures, and signal stations exchange information. It introduces the three pattern families through a visual analogy, not a code diagram.

All 23 individual pattern covers are preserved from the site’s earlier learning collection. They illustrate analogies; the separate diagrams show the example’s structure. The overview cover was generated separately for this introduction; illustration provenance records its creation. Source code, adapted documentation, and diagrams retain the repository’s license notice.

Ahmed (Sanfor)Backend and automation engineer in Alexandria. I build the systems businesses run on, and paint between deploys.

Keep reading

Design PatternsAbstract Factory (Creational Pattern)5 minDesign PatternsAdapter (Structural Pattern)4 minDesign PatternsBridge (Structural Pattern)5 min

Have manual work eating your week?

Book a free call