Design Patterns - Behavioral
Strategy, Observer, Command, State, Template Method, Chain of Responsibility, and more.
Deutsche Übersetzung in Arbeit
Diese Lektion ist noch nicht ins Deutsche übersetzt und wird daher auf Englisch angezeigt. Der Rest der Seite ist vollständig lokalisiert.
Auf dieser Seite
Behavioral patterns govern how objects communicate and divide responsibility. They're about algorithms and the assignment of duties between objects. This is the largest pattern family - here are the essentials.
Strategy - swappable algorithms
Defines a family of interchangeable algorithms and lets you swap them at runtime.
Same destination, different strategies: fastest, shortest, avoid tolls. You pick one, and the app follows it. You can switch anytime without changing the app itself. Strategy encapsulates each algorithm behind a common interface so they're interchangeable.
interface SortStrategy { void sort(int[] data); }
class QuickSort implements SortStrategy { public void sort(int[] d) { } }
class BubbleSort implements SortStrategy { public void sort(int[] d) { } }
class Sorter {
private SortStrategy strategy;
Sorter(SortStrategy s) { this.strategy = s; }
void sort(int[] data) { strategy.sort(data); } // delegates to the chosen one
}This is composition and "program to an interface" in pattern form.
Observer - publish and subscribe
When one object changes, all its dependents are notified automatically. The backbone of event systems and UIs.
Subscribers sign up; when a new issue is published, everyone receives it automatically - the publisher doesn't know or care who's on the list. Add or remove subscribers anytime. That's Observer: a subject notifies its observers of changes.
interface Observer { void update(String news); }
class NewsAgency {
private final List<Observer> observers = new ArrayList<>();
void subscribe(Observer o) { observers.add(o); }
void publish(String news) {
observers.forEach(o -> o.update(news)); // notify all
}
}Command - actions as objects
Wraps a request as an object, so you can queue, log, or undo it.
interface Command { void execute(); void undo(); }
class AddTextCommand implements Command {
public void execute() { /* insert text */ }
public void undo() { /* remove it */ }
}Command powers undo/redo
By turning each action into an object with execute() and undo(), you can keep a history stack - the foundation of undo/redo in editors, plus task queues and macro recording.
State - behavior that changes with internal state
Lets an object alter its behavior when its internal state changes - as if it switched classes.
A traffic light behaves differently in each state: green lets cars go, red stops them, yellow warns. The same light, different behavior per state, with defined transitions between them. The State pattern models exactly this.
Template Method - a fixed skeleton with customizable steps
Defines the outline of an algorithm in a base class, letting subclasses fill in specific steps.
abstract class Report {
final void generate() { // the fixed skeleton
loadData();
formatData(); // subclass decides how
print();
}
abstract void formatData(); // the customizable step
void loadData() { }
void print() { }
}Chain of Responsibility - pass the request along
Passes a request through a chain of handlers until one handles it. Great for middleware, validation, and logging pipelines.
abstract class Handler {
protected Handler next;
Handler setNext(Handler n) { this.next = n; return n; }
abstract void handle(Request r); // handle, or pass to next
}Your issue goes to tier-1 support; if they can't solve it, they escalate to tier-2, then a specialist. Each level either handles it or passes it on. The sender doesn't need to know who ultimately resolves it.
The rest, briefly
| Pattern | Purpose |
|---|---|
| Iterator | Step through a collection without exposing its internals (Java's for-each) |
| Mediator | Centralize complex communication between objects (like a control tower) |
| Visitor | Add new operations to an object structure without changing its classes |
| Memento | Capture and restore an object's state (snapshots for undo) |
Don't force patterns
Patterns are tools, not goals
Recognizing when a pattern fits is a skill; forcing patterns everywhere is a common mistake that adds needless complexity. Use a pattern when it genuinely solves your problem more clearly than plain code - not to show you know it. The simplest solution that works still wins.
Quick check
You need several interchangeable algorithms (e.g. different sorting or pricing strategies) selectable at runtime. Which pattern?
Key takeaways
- Behavioral patterns govern how objects communicate and share responsibility.
- Strategy makes algorithms interchangeable behind a common interface.
- Observer notifies dependents automatically when a subject changes (pub/sub, events).
- Command wraps actions as objects, enabling queues, logging, and undo/redo.
- State changes behavior with internal state; Template Method fixes a skeleton with customizable steps.
- Chain of Responsibility passes a request along handlers; Iterator, Mediator, Visitor, and Memento round out the family.
- Apply patterns when they genuinely clarify - never force them.
One practical topic closes Stage 5: the coding conventions that keep Java code consistent and professional.