Chain of Responsibility cho phép pass request qua chain of handlers — mỗi handler quyết định xử lý hoặc pass cho handler tiếp theo.
- Express.js middleware là ví dụ hoàn hảo:
app.use(authMiddleware, rateLimitMiddleware, validationMiddleware, routeHandler)— mỗi middleware gọinext()để pass request.
Ví dụ TypeScript:
typescript
interface Handler {
setNext(h: Handler): Handler
handle(request: number): string | null
}
abstract class AbstractHandler implements Handler {
protected nextHandler?: Handler
setNext(h: Handler) {
this.nextHandler = h
return h
}
handle(r: number): string | null {
return this.nextHandler?.handle(r) ?? null
}
}
class AuthHandler extends AbstractHandler {
handle(r: number) {
if (r < 0) return 'Unauthorized'
return super.handle(r)
}
}- Dùng khi: nhiều object có thể handle request và muốn decouple sender từ receiver; khi handlers nên được configurable hoặc reorderable tại runtime.
- Khác Observer: Chain of Responsibility chỉ một handler xử lý; Observer notify tất cả.
- Không dùng khi: chain quá dài gây performance issue; khi không rõ handler nào sẽ xử lý gây khó debug.
Chain of Responsibility allows a request to pass through a chain of handlers — each handler decides whether to process it or pass it to the next.
- Express.js middleware is a perfect example:
app.use(authMiddleware, rateLimitMiddleware, validationMiddleware, routeHandler)— each middleware callsnext()to pass the request along. - TypeScript example:
typescript
interface Handler {
setNext(h: Handler): Handler
handle(request: number): string | null
}
abstract class AbstractHandler implements Handler {
protected nextHandler?: Handler
setNext(h: Handler) {
this.nextHandler = h
return h
}
handle(r: number): string | null {
return this.nextHandler?.handle(r) ?? null
}
}
class AuthHandler extends AbstractHandler {
handle(r: number) {
if (r < 0) return 'Unauthorized'
return super.handle(r)
}
}Use it when multiple objects may handle a request and you want to decouple the sender from the receiver, or when handlers should be configurable and reorderable at runtime.
- Difference from Observer: Chain of Responsibility has only one handler process the request; Observer notifies all observers.
- Avoid it when the chain is too long and causes performance issues, or when it's unclear which handler will act, making debugging difficult.