Behavioural Patterns
Behavioral patterns take care of effective communication and the assignment of responsibilities between objects.
Overview of Behavioral Patterns
Section titled “Overview of Behavioral Patterns”| Pattern | Purpose |
|---|---|
| Strategy | Define a family of algorithms, put each in a separate class, and make their objects interchangeable |
| Observer | Define a subscription mechanism to notify multiple objects about events happening to observed objects |
| Command | Turn requests into stand-alone objects containing all request information |
| Iterator | Traverse elements of a collection without exposing the underlying representation |
| State | Let an object alter its behavior when its internal state changes |
| Chain of Responsibility | Pass requests along a chain of handlers where each decides to process or forward |
| Template Method | Define the skeleton of an algorithm in a superclass, letting subclasses override specific steps |
| Visitor | Separate algorithms from the objects on which they operate |
| Mediator | Reduce chaotic dependencies by forcing objects to collaborate through a mediator |
| Memento | Store and restore the previous state of an object without revealing implementation details |
Strategy Pattern
Section titled “Strategy Pattern”Error generating PlantUML diagram: connect ECONNREFUSED 127.0.0.1:8080
@startumlhide empty membersskinparam backgroundColor #ffffffskinparam Shadowing falseskinparam DefaultFontName Arialskinparam DefaultFontSize 13skinparam ArrowColor #475569skinparam rectangleBorderColor #64748bskinparam rectangleBackgroundColor #f8fafcskinparam classBackgroundColor #f8fafcskinparam classBorderColor #64748bskinparam interfaceBackgroundColor #ecfdf5skinparam interfaceBorderColor #10b981skinparam noteBackgroundColor #fef3c7skinparam noteBorderColor #d97706
class Client { + main()}
class Context { - strategy: Strategy + setStrategy(Strategy) + executeStrategy()}
interface Strategy { + execute()}
class ConcreteStrategyA { + execute()}
class ConcreteStrategyB { + execute()}
class ConcreteStrategyC { + execute()}
Client --> ContextClient ..> ConcreteStrategyAClient ..> ConcreteStrategyBClient ..> ConcreteStrategyCContext o--> StrategyStrategy <|-- ConcreteStrategyAStrategy <|-- ConcreteStrategyBStrategy <|-- ConcreteStrategyC
note right of Context::executeStrategy strategy.execute()end note
note right of Client::main // Create strategies strategyA = new ConcreteStrategyA() strategyB = new ConcreteStrategyB()
// Create context context = new Context()
// Set and execute strategy A context.setStrategy(strategyA) context.executeStrategy()
// Switch to strategy B context.setStrategy(strategyB) context.executeStrategy()end note@endumlKey Components
Section titled “Key Components”- Context: Maintains a reference to a Strategy object and delegates it to execute the algorithm
- Strategy: Common interface for all concrete strategies
- ConcreteStrategy: Implements the algorithm using the Strategy interface
When to Use
Section titled “When to Use”Real-World Examples
Section titled “Real-World Examples”- Navigation Apps - Calculate routes using different strategies (fastest, shortest, avoid highways, public transport)
- Payment Processing - Different payment methods (credit card, PayPal, cryptocurrency)
- Compression Algorithms - Various compression strategies (ZIP, RAR, 7z)
- Sorting Algorithms - Different sorting implementations based on data characteristics
Observer Pattern
Section titled “Observer Pattern”Error generating PlantUML diagram: connect ECONNREFUSED 127.0.0.1:8080
@startumlhide empty members
skinparam backgroundColor #ffffffskinparam Shadowing falseskinparam DefaultFontName Arialskinparam DefaultFontSize 13skinparam ArrowColor #475569skinparam rectangleBorderColor #64748bskinparam rectangleBackgroundColor #f8fafcskinparam classBackgroundColor #f8fafcskinparam classBorderColor #64748bskinparam interfaceBackgroundColor #ecfdf5skinparam interfaceBorderColor #10b981skinparam noteBackgroundColor #fef3c7skinparam noteBorderColor #d97706
class Client { + main()}
class Subject { - observers: List<Observer> - state: State + attach(Observer) + detach(Observer) + setState(State) + notify()}
interface Observer { + update()}
class ConcreteObserverA { + update()}
class ConcreteObserverB { + update()}
Client --> SubjectClient --> ConcreteObserverAClient --> ConcreteObserverBSubject o--> ObserverObserver <|-- ConcreteObserverAObserver <|-- ConcreteObserverB
note right of Subject::notify for each observer in observers: observer.update()end note
note right of Subject::setState this.state = state notify() // Notify all observersend note
note right of Client::main // Create subject and observers subject = new Subject() observerA = new ConcreteObserverA() observerB = new ConcreteObserverB()
// Register observers subject.attach(observerA) subject.attach(observerB)
// Change state - triggers notification subject.setState(newState)
// Unregister an observer subject.detach(observerB)end note@endumlKey Components
Section titled “Key Components”- Subject: Maintains a list of observers and notifies them of state changes
- Observer: Interface that defines the update method for objects that should be notified
- ConcreteObserver: Implements the Observer interface to respond to updates
When to Use
Section titled “When to Use”Real-World Examples
Section titled “Real-World Examples”- UI Event Listeners - Button clicks, form submissions, keyboard events
- Subscription Systems - YouTube channels, newsletters, RSS feeds
- Stock Market Feeds - Real-time price updates to multiple traders
- Social Media - Notification systems for likes, comments, and shares
Command Pattern
Section titled “Command Pattern”Error generating PlantUML diagram: connect ECONNREFUSED 127.0.0.1:8080
@startumlhide empty members
skinparam backgroundColor #ffffffskinparam Shadowing falseskinparam DefaultFontName Arialskinparam DefaultFontSize 13skinparam ArrowColor #475569skinparam rectangleBorderColor #64748bskinparam rectangleBackgroundColor #f8fafcskinparam classBackgroundColor #f8fafcskinparam classBorderColor #64748bskinparam interfaceBackgroundColor #ecfdf5skinparam interfaceBorderColor #10b981skinparam noteBackgroundColor #fef3c7skinparam noteBorderColor #d97706
class Client { + main()}
class Invoker { - command: Command + setCommand(Command) + executeCommand()}
interface Command { + execute()}
class ConcreteCommand { - receiver: Receiver + execute()}
class Receiver { + action()}
Client --> Receiver: creates >Client --> ConcreteCommand: creates >Client --> Invoker: configures >Invoker o--> CommandCommand <|-- ConcreteCommandConcreteCommand --> Receiver
note right of ConcreteCommand::execute receiver.action()end note
note right of Invoker::command // can optionally contain // to maintain history / undo / redo commandStack: Stackend note
note right of Client::main // Create receiver receiver = new Receiver()
// Create command with receiver command = new ConcreteCommand(receiver)
// Setup invoker with command invoker = new Invoker() invoker.setCommand(command)
// Execute the command invoker.executeCommand()end note
note "Commands encapsulate actions\nand their parameters" as N1@endumlKey Components
Section titled “Key Components”- Command - Interface with an execute method
- ConcreteCommand - Implements Command and links to a Receiver
- Invoker - Asks the command to carry out the action
- Receiver - Knows how to perform the operations
When to Use
Section titled “When to Use”Real-World Examples
Section titled “Real-World Examples”- Remote Controls - TV remotes, smart home devices
- Text Editors - Undo/redo functionality
- Game Commands - Action queues, replay systems
- Task Schedulers - Job queues, batch processing
- Transactional Systems - Database transactions with rollback
Iterator Pattern
Section titled “Iterator Pattern”Error generating PlantUML diagram: connect ECONNREFUSED 127.0.0.1:8080
@startumlskinparam backgroundColor #ffffffskinparam Shadowing falseskinparam DefaultFontName Arialskinparam DefaultFontSize 13skinparam ArrowColor #475569skinparam rectangleBorderColor #64748bskinparam rectangleBackgroundColor #f8fafcskinparam classBackgroundColor #f8fafcskinparam classBorderColor #64748bskinparam interfaceBackgroundColor #ecfdf5skinparam interfaceBorderColor #10b981skinparam noteBackgroundColor #fef3c7skinparam noteBorderColor #d97706
class Client { + main()}
interface Iterator { + hasNext(): boolean + next(): Object}
class ConcreteIterator { - collection: ConcreteCollection - position: int + hasNext(): boolean + next(): Object}
interface Collection { + createIterator(): Iterator}
class ConcreteCollection { - items: Object[] + createIterator(): Iterator}
Client --> Collection: uses >Client --> Iterator: uses >Collection <|-- ConcreteCollectionIterator <|-- ConcreteIteratorConcreteCollection ..> ConcreteIterator: creates >
note right of Client::main // Get collection collection = new ConcreteCollection()
// Get iterator from collection iterator = collection.createIterator()
// Iterate through elements while (iterator.hasNext()) { item = iterator.next() // Process item }end note
note right of ConcreteCollection::createIterator return new ConcreteIterator(this)end note
note "Iterator provides a way to access\nelements sequentially without\nexposing underlying structure" as N1@endumlKey Components
Section titled “Key Components”- Iterator: Interface with methods for traversing a collection
- ConcreteIterator: Implements the Iterator interface
- Collection: Interface that creates an Iterator
- ConcreteCollection: Implements Collection and returns ConcreteIterator
When to Use
Section titled “When to Use”Real-World Examples
Section titled “Real-World Examples”- Java Collections - Iterator and Iterable interfaces
- Database Result Sets - Cursor-based record traversal
- File Systems - Directory tree traversal
- Social Media Feeds - Infinite scroll pagination
State Pattern
Section titled “State Pattern”Error generating PlantUML diagram: connect ECONNREFUSED 127.0.0.1:8080
@startumlskinparam backgroundColor #ffffffskinparam Shadowing falseskinparam DefaultFontName Arialskinparam DefaultFontSize 13skinparam ArrowColor #475569skinparam rectangleBorderColor #64748bskinparam rectangleBackgroundColor #f8fafcskinparam classBackgroundColor #f8fafcskinparam classBorderColor #64748bskinparam interfaceBackgroundColor #ecfdf5skinparam interfaceBorderColor #10b981skinparam noteBackgroundColor #fef3c7skinparam noteBorderColor #d97706
class Client { + main()}
class Context { - state: State + setState(State) + request()}
interface State { + handle(Context)}
class ConcreteStateA { + handle(Context)}
class ConcreteStateB { + handle(Context)}
Client --> Context: uses >Context o--> StateState <|-- ConcreteStateAState <|-- ConcreteStateB
note right of Context::request state.handle(this)end note
note right of ConcreteStateA::handle // Do something // May change context's state context.setState(new ConcreteStateB())end note
note right of Client::main // Create context with initial state initialState = new ConcreteStateA() context = new Context() context.setState(initialState)
// Request actions - state changes internally context.request() // In state A context.request() // Now in state B
// Client doesn't need to track state changesend note
note "State transitions are controlled\nby the concrete state classes" as N1@endumlKey Components
Section titled “Key Components”- Context: Maintains a reference to a State object and delegates state-specific behavior
- State: Interface defining state-specific behavior
- ConcreteState: Classes that implement specific states’ behavior
When to Use
Section titled “When to Use”Real-World Examples
Section titled “Real-World Examples”- Order Processing - States: ordered → paid → shipped → delivered
- Document Workflow - States: draft → review → approved → published
- Media Players - States: playing, paused, stopped, buffering
- TCP Connections - States: closed, listen, established, closing
- Vending Machines - States: idle, selecting, dispensing, out of stock
Chain of Responsibility Pattern
Section titled “Chain of Responsibility Pattern”Error generating PlantUML diagram: connect ECONNREFUSED 127.0.0.1:8080
@startumlskinparam backgroundColor #ffffffskinparam Shadowing falseskinparam DefaultFontName Arialskinparam DefaultFontSize 13skinparam ArrowColor #475569skinparam rectangleBorderColor #64748bskinparam rectangleBackgroundColor #f8fafcskinparam classBackgroundColor #f8fafcskinparam classBorderColor #64748bskinparam interfaceBackgroundColor #ecfdf5skinparam interfaceBorderColor #10b981skinparam noteBackgroundColor #fef3c7skinparam noteBorderColor #d97706
class Client { + main()}
class Request { - type: String - content: String + getType(): String + getContent(): String}
abstract class Handler { - successor: Handler + setSuccessor(Handler) + handleRequest(Request)}
class ConcreteHandlerA { + handleRequest(Request)}
class ConcreteHandlerB { + handleRequest(Request)}
class ConcreteHandlerC { + handleRequest(Request)}
Client --> Handler: uses >Client --> Request: creates >Handler <|-- ConcreteHandlerAHandler <|-- ConcreteHandlerBHandler <|-- ConcreteHandlerCHandler o--> Handler
note right of Handler::handleRequest if (can handle request) handle it else if (successor != null) successor.handleRequest(request)end note
note right of Client::main // Create the chain of handlers handlerA = new ConcreteHandlerA() handlerB = new ConcreteHandlerB() handlerC = new ConcreteHandlerC()
// Build the chain handlerA.setSuccessor(handlerB) handlerB.setSuccessor(handlerC)
// Create and process requests request1 = new Request("Type1", "Process this") request2 = new Request("Type3", "Handle this")
// Send requests to first handler in chain handlerA.handleRequest(request1) handlerA.handleRequest(request2)end note
note "Each handler decides either to\nprocess the request or pass\nit to the next handler" as N1@endumlKey Components
Section titled “Key Components”- Handler: Abstract class/interface defining the request handling method and successor link
- ConcreteHandler: Implements the request handling behavior
When to Use
Section titled “When to Use”Real-World Examples
Section titled “Real-World Examples”- HTTP Middleware - Authentication → logging → compression → response
- Event Propagation - UI event bubbling in DOM hierarchy
- Approval Workflows - Employee → manager → director → VP
- Exception Handling - Try-catch chains in error processing
- Logging Frameworks - Different log levels (debug, info, warn, error)
Template Method Pattern
Section titled “Template Method Pattern”Error generating PlantUML diagram: connect ECONNREFUSED 127.0.0.1:8080
@startumlskinparam backgroundColor #ffffffskinparam Shadowing falseskinparam DefaultFontName Arialskinparam DefaultFontSize 13skinparam ArrowColor #475569skinparam rectangleBorderColor #64748bskinparam rectangleBackgroundColor #f8fafcskinparam classBackgroundColor #f8fafcskinparam classBorderColor #64748bskinparam interfaceBackgroundColor #ecfdf5skinparam interfaceBorderColor #10b981skinparam noteBackgroundColor #fef3c7skinparam noteBorderColor #d97706
class Client { + main()}
abstract class AbstractClass { + templateMethod() # {abstract} primitiveOperation1() # {abstract} primitiveOperation2() # hook()}
class ConcreteClassA { # primitiveOperation1() # primitiveOperation2()}
class ConcreteClassB { # primitiveOperation1() # primitiveOperation2() # hook()}
Client --> ConcreteClassA: uses >Client --> ConcreteClassB: uses >AbstractClass <|-- ConcreteClassAAbstractClass <|-- ConcreteClassB
note right of AbstractClass::templateMethod primitiveOperation1() primitiveOperation2() hook() // Algorithm structure is fixedend note
note right of Client::main // Create concrete implementations classA = new ConcreteClassA() classB = new ConcreteClassB()
// Call template method on each // Steps are defined in subclasses classA.templateMethod() classB.templateMethod()
// Client uses the same interface // but gets different implementationsend note
note "Template Method defines the skeleton\nof an algorithm, with concrete steps\ndefined by subclasses" as N1@endumlKey Components
Section titled “Key Components”- AbstractClass: Defines template methods and abstract operations
- ConcreteClass: Implements the primitive operations required by the template method
When to Use
Section titled “When to Use”Real-World Examples
Section titled “Real-World Examples”- Framework Lifecycle - React component lifecycle, Spring bean lifecycle
- Data Processing - ETL pipelines (extract → transform → load)
- Document Generation - Report templates with customizable sections
- Testing Frameworks - setUp → test → tearDown
- Game Development - Game loop: initialize → update → render
Visitor Pattern
Section titled “Visitor Pattern”Error generating PlantUML diagram: connect ECONNREFUSED 127.0.0.1:8080
@startumlskinparam backgroundColor #ffffffskinparam Shadowing falseskinparam DefaultFontName Arialskinparam DefaultFontSize 13skinparam ArrowColor #475569skinparam rectangleBorderColor #64748bskinparam rectangleBackgroundColor #f8fafcskinparam classBackgroundColor #f8fafcskinparam classBorderColor #64748bskinparam interfaceBackgroundColor #ecfdf5skinparam interfaceBorderColor #10b981skinparam noteBackgroundColor #fef3c7skinparam noteBorderColor #d97706
class Client { + main()}
class ObjectStructure { - elements: List<Element> + accept(Visitor)}
interface Visitor { + visitConcreteElementA(ConcreteElementA) + visitConcreteElementB(ConcreteElementB)}
class ConcreteVisitor1 { + visitConcreteElementA(ConcreteElementA) + visitConcreteElementB(ConcreteElementB)}
class ConcreteVisitor2 { + visitConcreteElementA(ConcreteElementA) + visitConcreteElementB(ConcreteElementB)}
interface Element { + accept(Visitor)}
class ConcreteElementA { + accept(Visitor) + operationA()}
class ConcreteElementB { + accept(Visitor) + operationB()}
Client --> ObjectStructure: uses >Client --> ConcreteVisitor1: creates >Client --> ConcreteVisitor2: creates >ObjectStructure o--> ElementVisitor <|-- ConcreteVisitor1Visitor <|-- ConcreteVisitor2Element <|-- ConcreteElementAElement <|-- ConcreteElementB
note right of ConcreteElementA::accept visitor.visitConcreteElementA(this)end note
note right of ObjectStructure::accept for each element in elements: element.accept(visitor)end note
note right of Client::main // Create object structure with elements structure = new ObjectStructure() structure.add(new ConcreteElementA()) structure.add(new ConcreteElementB())
// Create different visitors visitor1 = new ConcreteVisitor1() visitor2 = new ConcreteVisitor2()
// Apply visitors to the structure structure.accept(visitor1) structure.accept(visitor2)
// Same elements, different operationsend note
note "Visitor separates algorithms\nfrom the objects they operate on" as N1@endumlKey Components
Section titled “Key Components”- Visitor: Interface declaring visit methods for each element type
- ConcreteVisitor: Implements the visitor interface with specific behavior
- Element: Interface declaring an accept method
- ConcreteElement: Implements the element interface
When to Use
Section titled “When to Use”Real-World Examples
Section titled “Real-World Examples”- Compiler Design - Abstract syntax tree (AST) traversal and analysis
- Document Processing - XML/HTML DOM operations (rendering, validation, transformation)
- Report Generation - Different export formats (PDF, HTML, JSON) from same data structure
- Tax Calculation - Computing taxes for different product types
- Graphics Rendering - Rendering different shape types
Mediator Pattern
Section titled “Mediator Pattern”Error generating PlantUML diagram: connect ECONNREFUSED 127.0.0.1:8080
@startumlskinparam backgroundColor #ffffffskinparam Shadowing falseskinparam DefaultFontName Arialskinparam DefaultFontSize 13skinparam ArrowColor #475569skinparam rectangleBorderColor #64748bskinparam rectangleBackgroundColor #f8fafcskinparam classBackgroundColor #f8fafcskinparam classBorderColor #64748bskinparam interfaceBackgroundColor #ecfdf5skinparam interfaceBorderColor #10b981skinparam noteBackgroundColor #fef3c7skinparam noteBorderColor #d97706
class Client { + main()}
interface Mediator { + notify(Colleague, Event)}
class ConcreteMediator { - colleagueA: ConcreteColleagueA - colleagueB: ConcreteColleagueB + setColleagueA(ConcreteColleagueA) + setColleagueB(ConcreteColleagueB) + notify(Colleague, Event)}
abstract class Colleague { # mediator: Mediator + setMediator(Mediator)}
class ConcreteColleagueA { + operationA() + receiveFromB()}
class ConcreteColleagueB { + operationB() + receiveFromA()}
Client --> ConcreteMediator: creates >Client --> ConcreteColleagueA: creates >Client --> ConcreteColleagueB: creates >Mediator <|-- ConcreteMediatorColleague <|-- ConcreteColleagueAColleague <|-- ConcreteColleagueBColleague o--> MediatorConcreteMediator --> ConcreteColleagueAConcreteMediator --> ConcreteColleagueB
note right of ConcreteMediator::notify if (sender == colleagueA && event == "A_EVENT") colleagueB.receiveFromA() else if (sender == colleagueB && event == "B_EVENT") colleagueA.receiveFromB()end note
note right of Client::main // Create mediator mediator = new ConcreteMediator()
// Create colleagues colleagueA = new ConcreteColleagueA() colleagueB = new ConcreteColleagueB()
// Register colleagues with mediator mediator.setColleagueA(colleagueA) mediator.setColleagueB(colleagueB)
// Set mediator for colleagues colleagueA.setMediator(mediator) colleagueB.setMediator(mediator)
// Colleagues communicate through mediator colleagueA.operationA() // Triggers notificationend note
note "Mediator centralizes complex\ncommunication between objects" as N1@endumlKey Components
Section titled “Key Components”- Mediator: Interface defining communication method between colleagues
- ConcreteMediator: Implements Mediator and coordinates between colleague objects
- Colleague: Abstract class for objects that communicate through the mediator
- ConcreteColleague: Implements Colleague with specific behavior
When to Use
Section titled “When to Use”Real-World Examples
Section titled “Real-World Examples”- Air Traffic Control - Centralized coordination of aircraft communication
- Chat Rooms - Server mediates messages between users
- UI Dialog Boxes - Coordinating interactions between form elements
- Stock Exchange - Mediating trades between buyers and sellers
- Smart Home Systems - Central hub coordinating device interactions
Memento Pattern
Section titled “Memento Pattern”Error generating PlantUML diagram: connect ECONNREFUSED 127.0.0.1:8080
@startumlskinparam backgroundColor #ffffffskinparam Shadowing falseskinparam DefaultFontName Arialskinparam DefaultFontSize 13skinparam ArrowColor #475569skinparam rectangleBorderColor #64748bskinparam rectangleBackgroundColor #f8fafcskinparam classBackgroundColor #f8fafcskinparam classBorderColor #64748bskinparam interfaceBackgroundColor #ecfdf5skinparam interfaceBorderColor #10b981skinparam noteBackgroundColor #fef3c7skinparam noteBorderColor #d97706
class Client { + main()}
class Originator { - state: String + setState(String) + getState(): String + createMemento(): Memento + restore(Memento)}
class Memento { - state: String + getState(): String}
class Caretaker { - mementos: List<Memento> + addMemento(Memento) + getMemento(int): Memento}
Client --> Originator: uses >Client --> Caretaker: uses >Originator --> Memento: creates >Caretaker o--> Memento: stores >
note right of Originator::createMemento return new Memento(state)end note
note right of Originator::restore setState(memento.getState())end note
note right of Client::main // Create originator with initial state originator = new Originator() originator.setState("State 1") System.out.println(originator.getState())
// Create caretaker to track history caretaker = new Caretaker()
// Save current state caretaker.addMemento(originator.createMemento())
// Change state and save again originator.setState("State 2") System.out.println(originator.getState()) caretaker.addMemento(originator.createMemento())
// Change state once more originator.setState("State 3") System.out.println(originator.getState())
// Restore to previous state originator.restore(caretaker.getMemento(1)) System.out.println("Restored to: " + originator.getState())
// Restore to first state originator.restore(caretaker.getMemento(0)) System.out.println("Restored to: " + originator.getState())end note
note "Memento captures and externalizes\nan object's state for later restoration" as N1@endumlKey Components
Section titled “Key Components”- Originator: Creates a memento containing its state and uses it to restore state
- Memento: Stores the internal state of the Originator
- Caretaker: Keeps track of multiple mementos
When to Use
Section titled “When to Use”Real-World Examples
Section titled “Real-World Examples”- Text Editors - Undo/redo functionality for document changes
- Video Games - Save game states, checkpoints
- Database Systems - Transaction rollback mechanisms
- Version Control - Saving and restoring file states
- Drawing Applications - History of drawing operations
- Form Wizards - Saving progress across multiple steps