Architecture

Behavioral Design Patterns: Coordinating Responsibilities with Flexibility

Design intelligent object interactions and workflows—master Observer, Strategy, Command, and State patterns that transform rigid, coupled systems into flexible, event-driven architectures that adapt to changing business rules

Series: Design Patterns and Analysis | Part 4 of 4 > Developed during Master’s in Web Systems Projects

We’ve reached the final chapter of this design patterns series. Once your objects are built (Creational Patterns) and structured (Structural Patterns), the next challenge is interaction.

Behavioral Design Patterns are all about how objects communicate, distribute responsibilities, and respond to events in a flexible, maintainable way.

These patterns help reduce complex conditional logic, prevent tight coupling, and increase clarity.

What Are Behavioral Patterns?

They describe common ways for objects to interact and cooperate, without knowing too much about each other’s internal details.

Use them when:

  • You need to change the behavior of objects at runtime
  • You want to avoid bloated switch/case blocks or chained if-else
  • You want to keep responsibilities focused and interactions modular

Types of Behavioral Patterns

Chain of Responsibility

Passes a request along a chain of handlers until one can process it.

  • Intent: Avoid coupling sender and receiver of a request.
  • Use When: You have a sequence of handlers with fallback logic.
UML Diagram of Chain of Responsibility
abstract class Handler {
    protected Handler next;
    public void setNext(Handler next) { this.next = next; }
    public void handle(Request req) {
        if (canHandle(req)) process(req);
        else if (next != null) next.handle(req);
    }
}

Command

Encapsulates a request as an object.

  • Intent: Parameterize actions with objects, queue operations, support undo.
  • Use When: You need action history or task scheduling.
UML Diagram of Command
interface Command {
    void execute();
}

class LightOnCommand implements Command {
    Light light;
    void execute() { light.turnOn(); }
}

Iterator

Provides a way to access elements of a collection sequentially.

  • Intent: Decouple iteration logic from the collection itself.
  • Use When: You want standard iteration across different structures.
UML Diagram of Iterator
interface Iterator<T> {
    boolean hasNext();
    T next();
}

Mediator

Centralizes communication between objects.

  • Intent: Reduce coupling between components by introducing a mediator object.
  • Use When: You have complex many-to-many communication.
UML Diagram of Mediator
interface Mediator {
    void notify(Component sender, String event);
}

Memento

Captures and restores an object’s internal state.

  • Intent: Provide undo functionality without exposing internal state.
  • Use When: You need checkpoint and restore operations.
UML Diagram of Memento
class EditorMemento {
    private String content;
    public String getContent() { return content; }
}

Observer

Notifies dependent objects when a subject changes state.

  • Intent: One-to-many dependency without tight coupling.
  • Use When: You want event-driven architecture.
UML Diagram of Observer
interface Observer {
    void update();
}

class Subject {
    List<Observer> observers;
    void notifyAll() {
        for (Observer obs : observers) obs.update();
    }
}

State

Changes an object’s behavior when its state changes.

  • Intent: Represent different states as objects.
  • Use When: You have complex conditional logic dependent on state.
UML Diagram of State
interface State {
    void handle(Context context);
}

Strategy

Defines a family of interchangeable algorithms.

  • Intent: Separate algorithm logic from the context where it’s used.
  • Use When: You want to switch behavior at runtime.
UML Diagram of Strategy
interface SortStrategy {
    void sort(List data);
}

class QuickSort implements SortStrategy { ... }
class MergeSort implements SortStrategy { ... }

Template Method

Defines the skeleton of an algorithm, letting subclasses implement steps.

  • Intent: Preserve the structure of an operation but allow customization.
  • Use When: You want base logic with overridable hooks.
UML Diagram of Template Method
abstract class DataParser {
    public final void parse() {
        readData();
        processData();
        writeData();
    }
    protected abstract void readData();
    protected abstract void processData();
    protected abstract void writeData();
}

Visitor

Separates operations from the objects on which they operate.

  • Intent: Add operations to object structures without modifying them.
  • Use When: You need to perform multiple unrelated operations on a structure.
UML Diagram of Visitor
interface Visitor {
    void visit(Book book);
    void visit(Fruit fruit);
}

Comparison Table

PatternBest ForHelps Avoid
Chain of ResponsibilitySequential fallback logicNested conditionals
CommandAction history, UI buttonsTight sender-receiver coupling
IteratorStandard traversal of collectionsMixing logic and data structure
MediatorSimplifying object communicationComplex dependencies
MementoUndo functionalityLeaky internal state
ObserverEvent systems, reactive updatesManual dependency management
StateDynamic behavior changesBloated switch statements
StrategySwappable algorithmsHardcoded logic
Template MethodCustom steps in fixed processDuplicated code in subclasses
VisitorOperations on object hierarchiesPolluting classes with extra logic

Final Thoughts

Behavioral patterns provide the rules of interaction for objects in your system. They promote clarity, extensibility, and modularity in how logic is executed and coordinated.

With all three categories explored — Creational, Structural, Behavioral — we now have a solid foundation for software design that balances flexibility, clarity, and evolution.


Series Navigation