Handbooks / OOP & Design Patterns / Chapter 5

Behavioral Patterns

7 pages · ~5 min✓ Reviewed

Builds on Structural Patterns.

OOP & Design PatternsPage 1

Behavioral Patterns: The Mental Model

1. What They Are

  • Govern how objects communicate and share responsibility
  • Move variation (algorithm, reaction, request) out of the caller, behind an interface
PatternIntent
StrategySwap an algorithm
ObserverNotify dependents of a change
CommandTurn a request into an object
IteratorTraverse without exposing structure
StateBehavior changes with internal state
Template MethodFixed skeleton, subclass fills steps
Chain of ResponsibilityPass request along handlers until one handles it

2. Inheritance or Composition

Template MethodThe other six
Reuse viaInheritanceComposition
BoundCompile-time, subclassRuntime, swappable object
PatternsTemplate MethodStrategy, State, Command, Observer, Chain

3. The Smell

  • Long if/else or switch on type
  • A flag or state that picks behavior
  • Caller hard-wired to one concrete receiver
Remember

Spot the variation, then hide it behind an interface.

OOP & Design PatternsPage 2

Strategy, State and Template Method

1. Strategy and State

  • Strategy: client picks one algorithm object behind one interface
  • Context delegates; strategies never know each other
  • e.g. sort comparator, payment method, compression
  • State: context holds a current state and delegates
  • States replace the context's state themselves
  • e.g. TCP Open/Closed, Order Pending/Shipped
StrategyState
Class diagramidenticalidentical
Chosen byclientthe object itself
Over timestays fixedchanges automatically
Know each othernoyes

2. Template Method

  • Base class: a final method is the skeleton
  • It calls abstract steps and optional hooks
  • Subclasses override steps only
  • Hollywood principle: the base calls you, you don't call it
python
class Parser(ABC):
    def parse(self):  # skeleton, not overridden
        self.open()
        data = self.extract()
        self.close()
        return data

open and extract are abstract steps

3. Template Method vs Strategy

Template MethodStrategy
Variesparts of one algorithmthe whole algorithm
Mechanisminheritancecomposition
Boundcompile timeruntime
Template Method trap

A rigid, deep inheritance hierarchy. Need runtime swapping? Use Strategy.

OOP & Design PatternsPage 3

Observer, Command and Mediator-Free Messaging

1. Observer

  • Subject keeps a list of observers
  • subscribe / unsubscribe / notify() on change
  • One-to-many, loosely coupled
  • DOM addEventListener, Redux subscribe
javascript
const off = store.subscribe(render)
// later
off()

subscribe returns the unsubscribe function

  • Forgotten unsubscribe: lapsed listener, memory leak
  • Notification order is not guaranteed
  • Cascading updates can loop

2. Command

  • Request as an object with execute() and undo()
  • Holds the receiver and its arguments
  • Enables queues, logging, macros, undo/redo, retry
  • Examples: editor actions, job queue

3. Telling Them Apart

ObserverCommandStrategy
Sayssomething happeneddo thishow to do the job
Goes tomany unknown listenersone receiverits context
Receivernoyesno
Stored, replayednoyes, often undoableno
Remember

Observer = announce. Command = order. Strategy = method.

OOP & Design PatternsPage 4

Iterator and Chain of Responsibility

1. Iterator

  • Iterator = sequential access, structure stays hidden
  • next/hasNext, Python __iter__/__next__, JS Symbol.iterator, generators
  • One cursor per iterator, so independent traversals
  • Modify while iterating: Java ConcurrentModificationException, or skipped items
  • Exhausted iterator cannot be reused: ask for a new one

2. Chain of Responsibility

  • Each handler processes the request or passes it on
  • Sender does not know which handler acts
  • Examples: middleware, logging levels, support escalation
ClassicMiddleware
Who actsFirst handler that handles it, then stopEvery handler acts, then next()
Falls off the end

A request can go unhandled. Add a default terminal handler

3. Chain vs Command

ChainCommand
IntentRoutes one request to whichever handler can take itPackages a request for a known receiver
  • They combine well: commands passed through a handler chain
OOP & Design PatternsPage 5

Choosing the Right Pattern

1. Decision Rules

QuestionPattern
Swappable algorithm?Strategy
Behavior follows lifecycle status?State
Fixed steps, variable parts?Template Method
Many parties react to a change?Observer
Undo, queue or log of actions?Command
Unknown handler picks it up?Chain of Responsibility
Hide traversal?Iterator

2. Look-Alikes

PairDifference
Strategy / StateClient picks Strategy; State switches itself
Strategy / TemplateComposition (runtime) vs inheritance (compile time)
Command / StrategyCommand has a receiver, often undo; Strategy has neither
Observer / ChainObserver: all notified; Chain: first handler wins

3. Mistakes and Trade-off

  • State for two states: a boolean suffices
  • Strategy for an algorithm that never changes
  • Observer where a direct call is clearer
  • Template Method with a deep inheritance chain
Variation must be real

Every pattern adds classes and indirection. Apply it at the second or third variant.

OOP & Design PatternsPage 6

Behavioral Patterns Cheat Sheet

1. The Seven at a Glance

PatternCore ideaExample
Strategyswap algorithm at runtime; client-chosen; compositionsort comparator
Statebehavior follows internal state; objects drive transitionsorder lifecycle
Template Methodbase-class skeleton; subclasses fill steps; inheritanceframework lifecycle hooks
Observerone-to-many notifyevent listeners
Commandrequest as object; execute/undo; queue, replayeditor undo stack
Iteratortraverse without exposing structure; one cursor per traversalfor-each loop
Chainhandlers pass along until one handlesmiddleware

2. Telling Look-alikes Apart

PairDifference
Strategy / Stateclient switches vs state switches itself
Strategy / Templatecomposition vs inheritance
Command / StrategyCommand has a receiver and undo
Observer / Chainall notified vs first handler wins

3. Traps

  • Observer: forgotten unsubscribe leaks memory
  • Chain: add a default terminal handler
  • Template Method: deep hierarchies get rigid
Rule of thumb

Add a pattern at the second or third real variant, not before.

OOP & Design PatternsPage 7

Check yourself

Locked.press() sets door.state = Unlocked() once the code is right. Strategy or State?
  • State: the state object swaps itself on the context.
  • In Strategy the client picks the object and it stays fixed.
A widget subscribes to a store when it opens and never unsubscribes. It is then closed. What goes wrong?
  • The store still holds the widget, so it is never freed and still gets notified.
  • This is the lapsed listener leak; unsubscribe on close.
What does this print?
  • [1, 2, 3] then [].
  • The first call exhausts the iterator; call iter() again for a fresh cursor.
it = iter([1, 2, 3])
print(list(it))
print(list(it))