Knowledge Guide
HomeOO & Low-Level Design

Behavioral

Step 7 in the OO & Low-Level Design path · 10 concepts · 0 problems

0 / 10 complete

📘 Learn Behavioral from zero

From zero: creational patterns answer "how are objects instantiated"; structural patterns answer "how are objects composed and connected"; behavioral patterns answer "how do objects communicate and divide responsibility at runtime." Behavioral patterns are all about turning a verb, an algorithm, a request, a notification, a state-change, into an object you can swap, queue, or reroute.

Vivid analogy, the Strategy pattern as a navigation app. You want to go from home to office. The app does not bake one route-finder into its code. Instead it offers buttons: Drive, Walk, Cycle, Transit. Each is a self-contained algorithm behind the same interface, computeRoute(start, end). The app (the context) just holds whichever one you picked and calls that method. It never writes if (mode == DRIVE) ... else if (mode == WALK) .... Adding "Scooter" later means writing one new strategy class; the app code is untouched.

Concrete worked example. A checkout needs a shipping cost.

You have replaced a growing if/else with polymorphism, the open/closed principle in action: open to new behavior, closed to modification.

The single key insight: behavioral patterns convert a behavior, an algorithm, request, transition, or notification, into a first-class object so it can be selected, sequenced, or rerouted independently of the code that uses it. Favor composition over conditionals.

✨ Added by the guide to build intuition — not from the source course.

🎯 Guided practice

  1. Easy, Observer (a YouTube channel). A channel must notify all subscribers when it uploads. Step 1, find the one-to-many trigger: "when X changes, notify an unknown number of dependents", that is Observer. Step 2, define the contract: interface Subscriber { void update(String video); }. Step 3, the subject holds a list: Channel keeps List<Subscriber> subs with subscribe() and unsubscribe(). Step 4, push on change: upload(v) loops for (s : subs) s.update(v), O(number of subscribers). Step 5, decouple: Channel knows nothing about concrete subscriber types, only the interface, so an EmailSub or SMSSub can be added with zero changes to Channel. Watch out: a subscriber that is discarded but never unsubscribes keeps getting notified and cannot be garbage-collected (lapsed listener), so always pair subscribe with unsubscribe, or hold observers via weak references.
  2. Medium, State (a vending machine). Model states: NoCoin, HasCoin, Dispensing. Step 1, spot the smell: behavior (insertCoin, pressButton) depends on the current mode and you would otherwise write nested if (state == ...), that signals State. Step 2, make each state a class implementing interface State { void insertCoin(); void pressButton(); }. Step 3, the context delegates: VendingMachine holds State current and forwards every call, e.g. current.pressButton(). Step 4, states drive transitions: in NoCoin.insertCoin() call machine.setState(new HasCoin()); in HasCoin.pressButton() transition to Dispensing, then back to NoCoin once dispensed. Step 5, contrast with Strategy: here the state objects switch the context to one another based on transitions, whereas a Strategy is chosen once by the client and never reassigns itself, this is the canonical distinction interviewers probe. Result: adding a SoldOut state means one new class plus its transition edges, with no edits to a giant conditional that no longer exists.

✨ Added by the guide — work these before the full problem set.

Lessons in this topic