Behavioral 6 — Chain of Responsibility
In one line
Pass a request along a chain of handlers; each handler decides to process it or pass it on. Middleware, filters, validators.
Think of it like this
A customer-care call. First the bot tries; if it can't help, it passes you to an agent; if the agent can't, they pass you to a supervisor. Each level either solves it or passes it on.
Key ideas
- 01
Solves: pipelines of checks (auth, rate-limit, validate, log) or dynamic handler selection.
- 02
Handler holds next; handle() returns or delegates.
- 03
Modern variant: functional
handler.andThen(next)piping.
Java / Spring map
- →
Servlet Filters, Spring Gateway filters, Java Loggers, Spring Security filter chain.
Code & diagrams
API request middleware chain.
public interface Middleware {
void handle(HttpRequest req, Handler next);
}
public class AuthMiddleware implements Middleware {
public void handle(HttpRequest req, Handler next) {
if (!req.hasToken()) throw new Unauthorized();
next.handle(req);
}
}
public class RateLimitMiddleware implements Middleware {
public void handle(HttpRequest req, Handler next) {
if (!rateLimiter.allow(req.ip())) throw new TooManyRequests();
next.handle(req);
}
}
public class EnrichMiddleware implements Middleware {
public void handle(HttpRequest req, Handler next) {
req.attach("ts", System.currentTimeMillis());
next.handle(req);
}
}
// Registered in order:
// chain(auth).then(rateLimit).then(enrich).then(controller)
// Order matters and is config-driven — classic Gateway/Filter design.Explain without notes
How would you reorder or disable a step without touching the chain code?
Practice
Build an HTTP filter chain with auth, tenant-resolution, and logging for the API Gateway HLD.
Trade-offs
- ↔
Unbounded chain = debugging pain; keep the chain declarative and observable.
Completion checklist
I can build a middleware chain and explain why order matters (auth before rate limit? or after?).