- Behavioral patterns manage how objects communicate and assign behavior.
- They reduce long conditional logic by moving choices into collaborating objects.
- Common behavioral patterns:
- Strategy — swap an algorithm behind a stable interface.
- Observer — notify interested objects when state changes.
- Command — turn an action into an object.
- State — change behavior when an object's internal state changes.
- Template Method — define an algorithm skeleton and let subclasses fill in the steps.
- Chain of Responsibility — pass a request through handlers until one handles it.
- Iterator — traverse a collection without exposing its internals.
- Mediator — centralize interaction between many peer objects.
- Memento — capture and restore an object's state.
- Visitor — add operations over object structures without changing the structures.
- These patterns are most useful when behavior varies more often than the objects themselves.
classDiagram
class PaymentStrategy {
<<interface>>
+pay(amount)
}
class CardPayment {
+pay(amount)
}
class WalletPayment {
+pay(amount)
}
class Checkout {
-paymentStrategy PaymentStrategy
+complete(amount)
}
PaymentStrategy <|.. CardPayment
PaymentStrategy <|.. WalletPayment
Checkout --> PaymentStrategy
- Keeps business rules from collapsing into one large
if/elseblock. - Makes behavior easier to add, replace, test, and explain (OCP from topic 1 — SOLID).
- Decouples the object that triggers work from the object that performs it (DIP from topic 1 — SOLID).
- Helps model workflows with clear states and transitions.
- Supports undo, replay, notifications, and configurable rules at class level.
- Strategy vs. conditionals — Strategy is cleaner when algorithms change or multiply; conditionals are fine for two stable branches.
- Observer vs. direct calls — Observer reduces coupling, but event order and duplicate notifications must be considered.
- Command vs. plain method call — Command enables undo, ordered action lists, or history, but adds extra classes.
- State vs. flags — State objects avoid invalid flag combinations, but can feel heavy for simple objects.
- Chain vs. explicit routing — chains are flexible, but debugging can be harder if handler order is unclear.
- Visitor vs. adding methods — Visitor helps when operations change often, but makes adding new element types more expensive.
- Every behavioral pattern that uses a "do this behavior" interface is the same technique as the OCP discount policies from topic 1 (SOLID). The interface is the fixed contract; the implementations are the varying behaviors.
- Command's undo list often uses a Factory Method (topic 2 — creational) to create the right command from a user action string.
- Proxy (topic 3 — structural) and Command (behavioral) appear together: a Proxy can log calls and store them as Command objects for replay.
- Composite (topic 3 — structural) and Visitor (behavioral) are natural partners: Visitor adds operations over a Composite tree without changing the node classes.
- Observer and the notification factories from topic 2 often combine: the factory creates the right notification channel; the observer drives when to send.
- Requirement: a parking lot may assign the nearest spot, the first available spot, or the spot best suited to the vehicle size.
- Classes:
SpotSelectionStrategydefinesselectSpot(spots, vehicle).NearestSpotStrategy,FirstAvailableStrategy, andLargeSpotStrategyimplement it.ParkingLotdelegates spot choice to the strategy.
- Why it fits: the parking flow is stable, but the selection algorithm can change or be configured at runtime (OCP).
classDiagram
class ParkingLot {
-strategy SpotSelectionStrategy
+park(vehicle) Ticket
+setStrategy(strategy)
}
class SpotSelectionStrategy {
<<interface>>
+selectSpot(spots, vehicle) ParkingSpot
}
class NearestSpotStrategy {
+selectSpot(spots, vehicle) ParkingSpot
}
class FirstAvailableStrategy {
+selectSpot(spots, vehicle) ParkingSpot
}
class LargeSpotStrategy {
+selectSpot(spots, vehicle) ParkingSpot
}
ParkingLot --> SpotSelectionStrategy
SpotSelectionStrategy <|.. NearestSpotStrategy
SpotSelectionStrategy <|.. FirstAvailableStrategy
SpotSelectionStrategy <|.. LargeSpotStrategy
- Requirement: when an order moves from
PLACEDtoCONFIRMED, several downstream objects need to react. - Classes:
Orderkeeps a list ofOrderObserver.OrderObserverdefinesonStatusChanged(order, oldStatus, newStatus).ReceiptView,ActivityLog, andInventoryReservationimplement the observer.
- Why it fits:
Orderannounces the change without knowing every downstream reaction (SRP, DIP).
classDiagram
class Order {
-observers List~OrderObserver~
-status OrderStatus
+addObserver(o)
+removeObserver(o)
+setStatus(status)
}
class OrderObserver {
<<interface>>
+onStatusChanged(order, oldStatus, newStatus)
}
class ReceiptView {
+onStatusChanged(order, oldStatus, newStatus)
}
class ActivityLog {
+onStatusChanged(order, oldStatus, newStatus)
}
class InventoryReservation {
+onStatusChanged(order, oldStatus, newStatus)
}
Order --> OrderObserver
OrderObserver <|.. ReceiptView
OrderObserver <|.. ActivityLog
OrderObserver <|.. InventoryReservation
- Requirement: users can insert text, delete text, apply bold, and undo operations.
- Classes:
EditorCommanddefinesexecute()andundo().InsertTextCommand,DeleteTextCommand, andApplyStyleCommandeach store enough data to reverse themselves.Editorexecutes commands and stores completed commands inUndoStack.
- Why it fits: actions become objects, so history and undo are natural. New command types can be added without changing
Editor(OCP).
classDiagram
class EditorCommand {
<<interface>>
+execute()
+undo()
}
class InsertTextCommand {
-document Document
-position int
-text String
+execute()
+undo()
}
class DeleteTextCommand {
-document Document
-range TextRange
-deletedText String
+execute()
+undo()
}
class ApplyStyleCommand {
-document Document
-range TextRange
-style Style
+execute()
+undo()
}
class UndoStack {
-commands List~EditorCommand~
+push(command)
+pop() EditorCommand
+isEmpty() bool
}
class Editor {
-undoStack UndoStack
+execute(command)
+undo()
}
EditorCommand <|.. InsertTextCommand
EditorCommand <|.. DeleteTextCommand
EditorCommand <|.. ApplyStyleCommand
Editor --> UndoStack
UndoStack --> EditorCommand
- Requirement:
selectItem()should behave differently depending on whether money has been inserted, whether an item is being dispensed, or whether the machine is sold out. - Classes:
MachineStatedefinesinsertMoney(amount),selectItem(code), anddispense().IdleState,HasMoneyState,DispensingState, andSoldOutStateeach implement only valid behavior for their state.VendingMachinedelegates all user actions to the current state.
- Why it fits: invalid transitions return a message or no-op from the state class, instead of scattered flag checks everywhere.
classDiagram
class MachineState {
<<interface>>
+insertMoney(amount)
+selectItem(code)
+dispense()
}
class IdleState {
+insertMoney(amount)
+selectItem(code)
+dispense()
}
class HasMoneyState {
+insertMoney(amount)
+selectItem(code)
+dispense()
}
class DispensingState {
+insertMoney(amount)
+selectItem(code)
+dispense()
}
class SoldOutState {
+insertMoney(amount)
+selectItem(code)
+dispense()
}
class VendingMachine {
-state MachineState
-inventory Inventory
+setState(state)
+insertMoney(amount)
+selectItem(code)
+dispense()
}
MachineState <|.. IdleState
MachineState <|.. HasMoneyState
MachineState <|.. DispensingState
MachineState <|.. SoldOutState
VendingMachine --> MachineState
- Requirement: every board game follows setup, play turns, and declare winner, but each game fills the steps differently.
- Classes:
BoardGamedefinesstart()as:setupBoard(),assignPlayers(),playTurns(),declareWinner().ChessGameandTicTacToeGameoverride the abstract steps.
- Why it fits: the high-level flow is fixed while individual steps vary (OCP, SRP).
- Requirement: a support request should be handled by the first suitable handler in a chain.
- Classes:
SupportHandlerabstract class hashandle(request)and anextreference.FaqHandler,BillingHandler, andHumanReviewHandlereach decide whether they can handle a request; if not, they forward it.
- Why it fits: adding a new handler adds one class and one chain connection — existing handlers are not edited (OCP).
classDiagram
class SupportHandler {
<<abstract>>
-next SupportHandler
+setNext(handler) SupportHandler
+handle(request)
}
class FaqHandler {
+handle(request)
}
class BillingHandler {
+handle(request)
}
class HumanReviewHandler {
+handle(request)
}
SupportHandler <|-- FaqHandler
SupportHandler <|-- BillingHandler
SupportHandler <|-- HumanReviewHandler
SupportHandler --> SupportHandler : next
- Requirement: clients should traverse songs without knowing whether the playlist stores them in an array, a linked list, or grouped sections.
- Classes:
Playlistexposesiterator().PlaylistIteratorexposeshasNext()andnext().
- Why it fits: traversal logic is separated from the collection's internal representation (SRP).
- Requirement: users in a room send messages to each other without each user tracking every other user.
- Classes:
ChatMediatordefinessendMessage(sender, message).ChatRoomimplements the mediator, knows current participants, and routes messages.Userholds a reference to the mediator and sends through it.
- Why it fits: user-to-user coordination is centralized in one class (SRP). Users are decoupled from each other.
- Requirement: restore a document to a previous state on undo.
- Classes:
Documentcreates aDocumentSnapshotcapturing its current state.DocumentSnapshotstores state but does not expose mutable internals.Historystores a stack of snapshots.
- Why it fits: the document can be restored without letting outside classes directly manipulate its private fields.
- Relationship to Command: Command reverses one step at a time and is suited to fine-grained undo. Memento snapshots the whole document and is suited to bulk undo or "save before risky edit." Both can be used together — Command for normal edits, Memento before major operations.
- Requirement: calculate different reports over a drawing — total area, export text, and validation warnings.
- Classes:
ShapeVisitordefinesvisitCircle(c),visitRectangle(r), andvisitTextBox(t).- Each
Shapeimplementsaccept(visitor), which calls the visitor's matching method. AreaVisitor,ExportVisitor, andValidationVisitoreach implement the full set.
- Why it fits: new operations add one visitor class — no shape class changes (OCP). Visitor works naturally over a Composite tree from topic 3.