Design patterns are reusable solutions to recurring design problems. The Gang of Four book from 1994 catalogued 23 patterns split into three categories. They are not code snippets to paste in – they are a vocabulary for communicating design decisions. This post is an introduction and reference table before I cover each pattern individually in the coming weeks.
What a design pattern is – and what it is not
A design pattern is a description of a solution to a problem that appears repeatedly in different contexts. It captures the structure, roles and relationships between objects – not the concrete code. The same pattern can be implemented differently depending on the language and the framework.
Patterns are not:
- Silver bullets that solve every problem
- Rules that must be followed regardless of context
- Always the simplest solution – sometimes a plain function is better
Three categories of GoF patterns
Creational – how objects are created
| Pattern | Intent | In Magento 2 |
|---|---|---|
| Singleton | One instance per process | DI shared instances (default) |
| Factory Method | Subclass decides what to create | Auto-generated *Factory classes |
| Abstract Factory | Family of related objects | CollectionFactory + DataFactory pairs |
| Builder | Step-by-step complex object construction | SearchCriteriaBuilder |
| Prototype | Clone an existing object | Rarely used explicitly |
Structural – how objects are composed
| Pattern | Intent | In Magento 2 |
|---|---|---|
| Adapter | Make incompatible interfaces compatible | Payment gateway wrappers |
| Bridge | Separate abstraction from implementation | Cache frontend/backend split |
| Composite | Tree of objects treated uniformly | Category/product hierarchy |
| Decorator | Add responsibilities at runtime | Plugin system (Interceptors) |
| Facade | Simplified interface to a subsystem | Magento\Catalog\Helper\Data |
| Flyweight | Share objects to reduce memory | Attribute option pools |
| Proxy | Surrogate controlling access | Generated \Proxy classes (DI) |
Behavioural – how objects communicate
| Pattern | Intent | In Magento 2 |
|---|---|---|
| Chain of Responsibility | Pass request along a handler chain | Order validator chains |
| Command | Encapsulate operation as object | Message Queue consumers |
| Iterator | Sequential access without exposing structure | Collection iterators |
| Mediator | Centralise complex communications | Event Manager |
| Memento | Save and restore object state | Quote save/restore |
| Observer | Notify dependents of state changes | Event system (events.xml) |
| State | Behaviour changes with state | Order state machine |
| Strategy | Interchangeable algorithms | Shipping carrier calculations |
| Template Method | Skeleton algorithm, subclasses fill in | AbstractModel, AbstractBlock |
| Visitor | Add operations without changing classes | Quote address operations |
| Interpreter | Grammar and interpreter for a language | Rule condition expressions |
When NOT to use patterns
<?php
// This is fine. No pattern needed.
function formatPrice(float $amount, string $currency = 'PLN'): string
{
return number_format($amount, 2, ',', ' ') . ' ' . $currency;
}
// This is over-engineering for a simple task:
interface PriceFormatterInterface { public function format(float $amount): string; }
class PlnPriceFormatter implements PriceFormatterInterface { ... }
class AbstractPriceFormatterFactory { ... }
// ... just to call formatPrice()
Apply a pattern when you feel the pain it solves: growing if-else chains, hard-to-test code, changes that ripple across many classes. Not before.
Summary
The 23 GoF patterns are a shared vocabulary. When you say “Strategy” in a code review, every developer with pattern knowledge understands the structural implication immediately. Over the next weeks I will cover each pattern individually – implementation in PHP, a real-world use case, and where it appears in Magento 2.
