Memento for Iteration, Observer Pattern, and State Pattern (GoF Behavioral Patterns)
This excerpt covers three behavioral design patterns from the Gang of Four: the conclusion of the Memento pattern (focusing on its use for iteration), the complete Observer pattern, and the beginning of the State pattern. Together they address how objects manage state snapshots, propagate change notifications, and vary behavior based on internal state.
Key Concepts
Memento for iteration: Collections can use memento objects (IterationState) to externalize iteration state without breaking encapsulation — the collection interprets the memento, not the client
Observer pattern intent: Define a one-to-many dependency so that when one object changes state, all dependents are notified and updated automatically
Also known as: Dependents, Publish-Subscribe
Subject: Knows its observers, provides attach/detach interface; does not know concrete observer types
Observer: Defines an updating interface (Update method) for objects that should be notified of subject changes
Abstract coupling: Subject and Observer can belong to different abstraction layers — a lower-level subject can notify a higher-level observer without violating layering
Broadcast communication: Notifications go to all subscribed observers; the subject doesn't care how many exist
Unexpected updates risk: Observers are blind to each other's presence, so a simple subject change can trigger a cascade of expensive updates
Push vs Pull models: Push sends detailed change info (less reusable observers); Pull sends minimal notification and observers query for details (less efficient but more decoupled)
State pattern intent: Allow an object to alter its behavior when its internal state changes — the object appears to change its class
Also known as: Objects for States
State pattern key idea: Replace conditional logic (if/switch on state) with polymorphism — each state becomes a separate class implementing state-specific behavior
State transitions become explicit: Changing state means rebinding one variable (the state object), making transitions atomic from the context's perspective
Commands and Syntax
Memento-based iteration (C++):
Collection<ItemType*> aCollection;
IterationState* state;
state = aCollection.CreateInitialState();
while (!aCollection.IsDone(state)) {
aCollection.CurrentItem(state)->Process();
aCollection.Next(state);
}
delete state;
Memento + Iterator: Memento-based iteration avoids making iterator a friend of collection; instead Collection is a friend of IterationState
Memento + Command: Commands use mementos to maintain state for undoable operations
Observer + Mediator: A ChangeManager encapsulates complex update semantics, acting as mediator between subjects and observers
Observer + Singleton: ChangeManager is typically unique and globally accessible (Singleton)
Observer origin: Smalltalk MVC — Model is Subject, View is Observer
State + Flyweight: Stateless State objects (behavior-only, no instance variables) can be shared as flyweights
State vs table-driven FSM: State pattern models state-specific *behavior*; table-driven approach models state *transitions*
State eliminates conditionals: Same motivation as Strategy — replace conditional branches with polymorphic dispatch
Exam-Relevant Points
Observer provides abstract coupling — subject knows only the Observer interface, not concrete types; this allows cross-layer communication without violating layering
Push model = subject sends detailed change info (observers less reusable); Pull model = minimal notification, observers query (less efficient, more decoupled)
Self-consistency pitfall: Subject state must be consistent before calling Notify — use Template Method to ensure Notify is the last operation
Dangling references: When a subject is deleted, it must notify observers so they can reset references; simply deleting observers is not safe (they may observe other subjects)
ChangeManager (especially DAGChangeManager) prevents redundant updates when an observer watches multiple subjects — it is both a Mediator and typically a Singleton
Who triggers Notify: Subject auto-triggers (clients can't forget, but causes intermediate updates) vs. client-triggered (batches changes, but error-prone)
State pattern makes transitions explicit and atomic — rebinding one state object variable vs. scattered assignments to multiple data values
State objects with no instance variables can be shared across contexts as Flyweights
State decentralized transitions (state subclasses decide successors) are more flexible but introduce inter-subclass dependencies
Table-driven state machines vs State pattern: tables are regular and data-driven but less efficient than virtual dispatch and harder to attach actions to transitions
Memento-based iteration has two benefits: multiple simultaneous iteration states, and no encapsulation breach (unlike friend-based Iterator)