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().