Skip to main content

Behavioral Design Patterns

What Are Behavioral Patterns?​

Behavioral patterns deal with how objects communicate and distribute responsibility. While creational patterns focus on building objects and structural patterns on composing them, behavioral patterns focus on how they interact β€” who does what, and how messages flow between collaborators.

Why They Matter​

ProblemPattern That Solves It
Need to swap algorithms at runtimeStrategy
One object's state change should notify many othersObserver
Need to encapsulate a request as an object (undo, queue, log)Command
Need to traverse a collection without exposing its structureIterator
Objects should communicate without knowing about each other directlyMediator
Define an algorithm skeleton, let subclasses override stepsTemplate Method
Multiple handlers should process a request in orderChain of Responsibility
Object's behavior should change based on its internal stateState
Add operations to object structures without modifying the typesVisitor

The Coffee Shop Domain​

All examples continue with the Coffee Shop domain. We build on the same model:

public abstract class Coffee
{
public string Name { get; init; } = "";
public double Price { get; init; }
public List<string> Ingredients { get; init; } = new();
public CupSize Size { get; init; } = CupSize.Medium;

public override string ToString() =>
$"{Name} ({Size}) β€” ${Price:F2} [{string.Join(", ", Ingredients)}]";
}

public enum CupSize { Small, Medium, Large }

Pattern Comparison​

PatternIntentWhen to Use
StrategyEncapsulate interchangeable algorithmsPricing, sorting, compression strategies
ObserverOne-to-many dependency with automatic notificationEvents, pub/sub, UI data binding
CommandEncapsulate a request as an objectUndo/redo, task queues, macro recording
IteratorSequential access without exposing internalsCollection traversal, LINQ, pagination
MediatorCentralize communication between colleaguesUI dialog coordination, chat rooms, air traffic
Template MethodAlgorithm skeleton with overridable stepsFrameworks, lifecycle hooks, data processing
Chain of ResponsibilityPass request along a chain of handlersMiddleware, validation pipelines, logging
StateBehavior changes with internal stateVending machines, order status, game characters
VisitorAdd operations to a structure without changing itAST processing, report generation, serialization

Common Pitfalls​

  • Observer memory leaks: Forgetting to unsubscribe observers. In C#, use weak events or explicitly detach.
  • Mediator becoming a god object: The mediator coordinates, not contains business logic. Keep it thin.
  • Template Method and Hollywood Principle: Don't call us, we'll call you. Base class calls overrides, not the other way around.
  • Chain of Responsibility with no terminator: If no handler processes the request, it silently disappears. Always have a catch-all.