What is a Design Pattern?
A design pattern is a general, reusable solution to a commonly occurring problem in software design. It's not finished code, but rather a template or blueprint that can be applied to solve a particular design challenge in many different situations.
Origin
Design patterns were popularized by the "Gang of Four" (GoF) book Design Patterns: Elements of Reusable Object-Oriented Software (1994) by Gamma, Helm, Johnson, and Vlissides.
Pattern Categories
1. Creational Patterns
Control object creation mechanisms.
| Pattern | Purpose |
|---|---|
| Singleton | Ensure only one instance exists |
| Factory | Create objects without specifying exact class |
| Builder | Construct complex objects step by step |
| Prototype | Clone existing objects |
2. Structural Patterns
Compose objects into larger structures.
| Pattern | Purpose |
|---|---|
| Adapter | Make incompatible interfaces work together |
| Decorator | Add behavior to objects dynamically |
| Facade | Provide simplified interface to complex subsystem |
| Proxy | Control access to an object |
3. Behavioral Patterns
Define communication between objects.
| Pattern | Purpose |
|---|---|
| Observer | Notify dependents of state changes |
| Strategy | Define family of interchangeable algorithms |
| Command | Encapsulate requests as objects |
| Iterator | Access elements sequentially |
Examples
Singleton Pattern (Python)
class DatabaseConnection:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance.connection = cls._connect()
return cls._instance
@staticmethod
def _connect():
return "Connected to database"
# Both variables reference the same instance
db1 = DatabaseConnection()
db2 = DatabaseConnection()
print(db1 is db2) # True
Observer Pattern (TypeScript)
interface Observer {
update(data: any): void;
}
class Subject {
private observers: Observer[] = [];
subscribe(observer: Observer) {
this.observers.push(observer);
}
notify(data: any) {
this.observers.forEach(obs => obs.update(data));
}
}
Factory Pattern (Python)
class AnimalFactory:
@staticmethod
def create(animal_type: str):
if animal_type == "dog":
return Dog()
elif animal_type == "cat":
return Cat()
raise ValueError(f"Unknown animal: {animal_type}")
pet = AnimalFactory.create("dog")
Modern Alternatives
Some classic patterns are less relevant in modern languages:
- Iterator → Built into most languages (for...of, generators)
- Strategy → First-class functions / lambdas
- Singleton → Dependency injection containers
When to Use Patterns
✅ Do use when:
- You recognize a recurring problem
- The pattern fits naturally
- It improves code clarity
❌ Avoid when:
- Simpler solutions exist
- Over-engineering for future flexibility
- Pattern doesn't fit the problem