0/0
Design Patterns

Chain of Responsibility Pattern

A behavioral pattern that links handlers into a chain so each request gets a turn — handled, partially handled, or passed along — without the sender ever knowing who does the work.

Explore Topics

🎯
Intent
Let several handlers take a turn at a request
🏧 ATM Cash Dispenser Animator — watch the remainder propagate
Withdraw $
presets:
Handler chain · request flows left → right, remainder propagates
🏧
$230
→
rem $?
$100
Dollar100Dispenser
✓ 2× $100💵💵
out: $30
→
rem $30
$50
Dollar50Dispenser
⇢ passamount < 50
out: $30
→
rem $30
$20
Dollar20Dispenser
✓ 1× $20💵
out: $10
→
rem $10
$10
Dollar10Dispenser
✓ 1× $10💵
out: $0
Status:fully handled
Dispensed:2× $100, 0× $50, 1× $20, 1× $10· total 4 bills
Each handler decides independently: peel my denomination, or pass untouched. The chain mutates the request (remainder shrinks) until it hits zero — or falls off the end.
🎯
Intent
Let several handlers take a turn at a request

Chain of Responsibility (CoR) is a **behavioral** design pattern that gives more than one object a chance to handle a request. Handlers are wired into a linked list; a request enters the head and travels along until one handler claims it — or until the chain runs dry. The sender knows only the head, so it never has to ask "who can handle this?"

Key Ideas
  • A request walks a chain of handlers; each handler holds a reference to the **next**.
  • A handler can fully **handle** the request, **partially handle and forward the remainder**, or **forward untouched**.
  • The sender is decoupled from the concrete receiver — it talks only to the head.
  • Chain length, composition, and order are configurable **at runtime**, not at compile time.
Strengths
  • ✦Decouples sender from receiver — they never reference each other.
  • ✦New handlers slot in without editing existing code (Open/Closed Principle).
  • ✦Each handler keeps a single responsibility (SRP).
Weaknesses
  • △A request can fall off the end of the chain **unhandled** — easy to miss.
  • △Hard to trace at runtime — which handler actually did the work?
  • △Order of handlers silently encodes priority — wrong order, wrong result.
Used in:An ATM hands you a withdrawal: the $100 station takes the biggest chunk, then $50, then $20, then $10. Each station knows nothing about the others; it just peels off its share and passes the remainder along.
Code Snippets

Quiz

Intent Quiz
QUIZ 1/6
Which statement best captures the **intent** of Chain of Responsibility?

Diagrams

Chain of Responsibility — GoF structure
Loading diagram...
ATM dispense flow for $230 — request remainder propagates
Loading diagram...

Practice

Drag each line, method, or concept into the CoR participant it belongs to. Two items are traps — they do **not** belong to any CoR role.
EXERCISE 1/4
abstract void handle(Request req)
protected Handler next;
public Handler setNext(Handler h)
class Dollar50Dispenser extends DispenseChain
@Override void dispense(Currency c) { ... peel + forward remainder }
h100.setNext(h50).setNext(h20).setNext(h10);
head.handle(new Request(...));
instantiates handlers and configures the chain
new ConcurrentHashMap<>()
@FunctionalInterface annotation on Comparator
Handler (abstract base / interface)
Concrete Handler
Client
NOT part of CoR
The chain is broken — find the missing link
EXERCISE 2/4
Click on the line you think contains the bug, then press Confirm.
1DispenseChain h100 = new Dollar100Dispenser();
2DispenseChain h50 = new Dollar50Dispenser();
3DispenseChain h20 = new Dollar20Dispenser();
4DispenseChain h10 = new Dollar10Dispenser();
5
6h100.setNext(h50);
7h20.setNext(h10);
8
9h100.dispense(new Currency(230));
10// Expected: 2 x $100, 1 x $20, 1 x $10 (4 bills)
11// Actual: 2 x $100 — then silence
Order the six steps to implement Chain of Responsibility
EXERCISE 3/4
Drag the lines into the correct order.
4. Wire handlers in the Client with setNext, in priority order.
1. Define the Handler abstract class (with next field + setNext + abstract handle).
6. Add a Default / catch-all handler at the tail to make unhandled requests observable.
3. Decide the forwarding semantics: handle-then-stop, partial-handle-and-forward, or always-forward (broadcast).
2. Implement each Concrete Handler — only override the abstract method(s).
5. In the Client, call head.handle(request) — never reference handlers past the head.
8 common myths about Chain of Responsibility — true or false?
EXERCISE 4/4
Every handler in the chain must process the request.
The order of handlers in the chain never affects behavior.
A request can fall off the end of the chain unhandled — and the type system cannot prevent it.
Chain of Responsibility decouples the sender from the specific receiver.
Adding a new handler always requires modifying existing handler classes.
java.util.logging.Logger.log() walks the parent-logger chain to find handlers — a real-world CoR sighting in the JDK.
In every CoR implementation, each handler MUST call next.handle() at the end of its method.
Chain of Responsibility and Decorator have identical structure, so they are interchangeable.

References

📚

Gamma, Helm, Johnson, Vlissides — Design Patterns: Elements of Reusable Object-Oriented Software (GoF, 1994)

en.wikipedia.org

book
📄

Refactoring.guru — Chain of Responsibility

refactoring.guru

article
📄

Wikipedia — Chain-of-responsibility pattern

en.wikipedia.org

article
📄

Baeldung — Chain of Responsibility Design Pattern in Java

baeldung.com

article
📋

Java Servlet 4.0 Spec — javax.servlet.Filter (canonical JDK CoR)

docs.oracle.com

docs