Software Design & Architecture · Behavioral Patterns
Structural patterns decided how objects are put together. Behavioral patterns decide how they talk to each other — who walks a collection, and who gets told when something changes.
Behavioral patterns are responsible for the efficient and safe distribution of behaviors among a program's objects — how responsibility and communication are shared out at run time.
Gives clients one standard way to step through a collection — without ever revealing how that collection stores its elements internally.
Sets up a one-to-many link so that when one object changes state, everything depending on it is notified and updated automatically.
The lecture lists these so you recognise them as behavioral if they appear in a question: Command, Chain of Responsibility, Interpreter, Mediator, Memento, State, Strategy, Template Method and Visitor. Only Iterator and Observer are examinable in detail here.
Provides a standardized way of accessing and traversing the objects held in a collection data structure. Intent: provide a way to access the elements of a collection object sequentially, without any need to know its underlying representation.
createIterator(), and
(2) the Iterator interface to traverse the aggregate via next() and
hasNext(). Iterator1 implements the Iterator interface by accessing
Aggregate1. Note the client talks to interfaces on both sides — that is what
hides the representation.Setup: a NameRepository stores names in a plain array,
but the client should be able to walk it without knowing that. The concrete class implements
Container and holds an inner class
NameIterator that implements Iterator.
// The Iterator interface — the traversal contract public interface Iterator { public boolean hasNext(); public Object next(); } // The Aggregate / Container interface — the "give me an iterator" contract public interface Container { public Iterator getIterator(); } // Concrete collection + its concrete iterator as an inner class public class NameRepository implements Container { public String[] names = {"Robert", "John", "Julie", "Lora"}; public Iterator getIterator() { return new NameIterator(); } private class NameIterator implements Iterator { int index; // the iterator holds the position, NOT the collection public boolean hasNext() { return index < names.length; } public Object next() { if (this.hasNext()) return names[index++]; return null; } } } // Client — knows Container and Iterator, knows nothing about the array NameRepository namesRepository = new NameRepository(); for (Iterator iter = namesRepository.getIterator(); iter.hasNext(); ) { String name = (String) iter.next(); System.out.println("Name : " + name); } // → Name : Robert / Name : John / Name : Julie / Name : Lora
index lives on the
iterator, not on the collection. That is why you can hand out two iterators over the same
NameRepository and have them at different positions at the same time.Build a corporate directory that stores employee records in two different internal structures (say an array and a list) but lets a client traverse both uniformly — and offer two traversal methods: standard and reverse. Then name the pattern, draw the class diagram, and generate the code.
The answer: Iterator. One
EmployeeIterator interface; ArrayDirectory and
ListDirectory both implement the Aggregate interface; and because traversal logic
lives in the iterator, "reverse" is simply a second concrete iterator
(ReverseIterator) over the same collection — no change to the collection classes at
all. That last point is exactly benefit #3.
Standardizes the operations between objects that interoperate using a one-to-many relationship. Intent: define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
update().Observer type. On a state change it walks its list and calls
update() on each one. Adding a new kind of observer requires
no change to the Subject — that is where the pattern's flexibility comes from.Setup: a Subject holds a single
state integer. Three observers — BinaryObserver,
OctalObserver and HexaObserver — each render that same number in their own
base. Set the state once, and all three print.
// The Subject — keeps the list, owns the notification public class Subject { private List<Observer> observers = new ArrayList<>(); private int state; public int getState() { return state; } public void setState(int state) { this.state = state; notifyAllObservers(); // state changed → tell everyone, automatically } public void attach(Observer observer) { observers.add(observer); } public void notifyAllObservers() { for (Observer observer : observers) observer.update(); // iterate + update } } // The Observer abstraction — one abstract update() method public abstract class Observer { protected Subject subject; public abstract void update(); } // A concrete observer — registers itself with the subject in its constructor public class BinaryObserver extends Observer { public BinaryObserver(Subject subject) { this.subject = subject; this.subject.attach(this); // attach at construction time } public void update() { System.out.println("Binary String: " + Integer.toBinaryString(subject.getState())); } } // OctalObserver and HexaObserver are identical apart from the conversion call. // Client — attach once, then just change the state Subject subject = new Subject(); new HexaObserver(subject); new OctalObserver(subject); new BinaryObserver(subject); subject.setState(15); // → Hex: F · Octal: 17 · Binary: 1111 subject.setState(10); // → Hex: A · Octal: 12 · Binary: 1010
update() and never
touches the observers after construction. It changes one value —
setState() — and the fan-out happens inside the Subject. Delete an observer or add a
fourth one, and not a single line of Subject changes.update() interface method.update().update() method.A simplified Instagram or X. The Subject is an
Influencer who posts a status update and does not want to message every follower by
hand. The Observers are followers who subscribed and want to be
notified the moment a post goes live.
The task: give
Influencer a follower list plus follow(), unfollow() and
notifyFollowers(); define a Follower interface with
update(String post); then implement MobileAppUser and
WebBrowserUser, each printing something like
"Mobile User received notification: [Post Content]".
Note the mapping: follow/unfollow are
attach/detach, and notifyFollowers() is
notifyAllObservers(). Same pattern, renamed for the domain.
Same exam trick as last lecture: ask "what is this pattern actually solving?"
| Pattern | Solves | Relationship | Cue phrase |
|---|---|---|---|
| Iterator | A client needs to walk a collection without knowing how it stores its elements | One client ↔ one traversal at a time | "access the elements sequentially without exposing the representation" |
| Observer | Many objects need to react the moment one object's state changes | One Subject → many Observers | "one-to-many dependency, notified automatically" |
Look again at notifyAllObservers(): the Subject
iterates over its observer list to notify it. Observer uses
iteration internally — which is why these two land in the same lecture and why an exam question can
legitimately involve both at once.
| Category | Concerned with | This course's patterns |
|---|---|---|
| Creational | How objects get created | Abstract Factory, Factory Method, Singleton, Builder, Prototype |
| Structural | How classes and objects are composed into larger structures | Adapter, Composite, Facade |
| Behavioral | How behavior and communication are distributed among objects | Iterator, Observer |
Tap a card to flip it.
Written from this lecture's content — self-check practice, not an official past paper.
notifyAllObservers().