Loslegen
Javaneer
Zurück zur Stufe
Stufe 5·Software-Handwerk

Design Patterns - Behavioral

Strategy, Observer, Command, State, Template Method, Chain of Responsibility, and more.

26 Min. LesezeitExperte

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.

Strategy is like choosing a route in a maps app

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.

Observer is like a newsletter subscription

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.

State is like a traffic light

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
}
Chain of Responsibility is like customer support tiers

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

PatternPurpose
IteratorStep through a collection without exposing its internals (Java's for-each)
MediatorCentralize complex communication between objects (like a control tower)
VisitorAdd new operations to an object structure without changing its classes
MementoCapture 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.