Chain of Responsibility
O Chain of Responsibility é um padrão comportamental que permite passar uma requisição por uma cadeia de objetos até que algum deles consiga processá-la.
Em vez de ter um código cheio de if e else, podemos criar uma sequência de responsáveis.
Imagine um sistema de suporte:
Usuário
↓
Suporte Nível 1
↓
Suporte Nível 2
↓
Gerente
Cada nível tenta resolver o problema. Se não conseguir, passa para o próximo.
Exemplo
Criamos uma interface:
interface Handler {
setNext(handler: Handler): Handler;
handle(request: string): void;
}
Agora criamos uma classe base:
abstract class BaseHandler
implements Handler {
private next?: Handler;
setNext(handler: Handler): Handler {
this.next = handler;
return handler;
}
handle(request: string): void {
if (this.next) {
this.next.handle(request);
}
}
}
Criamos os responsáveis:
class BasicSupport
extends BaseHandler {
handle(request: string) {
if (request === "senha") {
console.log(
"Senha resetada pelo suporte básico"
);
return;
}
super.handle(request);
}
}
class TechnicalSupport
extends BaseHandler {
handle(request: string) {
if (request === "servidor") {
console.log(
"Problema resolvido pelo suporte técnico"
);
return;
}
super.handle(request);
}
}
class Manager
extends BaseHandler {
handle(request: string) {
console.log(
`Problema encaminhado ao gerente: ${request}`
);
}
}
Agora montamos a cadeia:
const basic =
new BasicSupport();
const technical =
new TechnicalSupport();
const manager =
new Manager();
basic
.setNext(technical)
.setNext(manager);
Podemos enviar requisições:
basic.handle("senha");
Resultado:
Senha resetada pelo suporte básico
Ou:
basic.handle("servidor");
Resultado:
Problema resolvido pelo suporte técnico
Ou:
basic.handle("reembolso");
Resultado:
Problema encaminhado ao gerente: reembolso
Exemplo prático: Middleware
Um dos exemplos mais conhecidos do conceito de Chain of Responsibility são os middlewares.
Imagine uma API:
Request
↓
Logger
↓
Autenticação
↓
Autorização
↓
Validação
↓
Controller
Cada middleware pode:
- Processar a requisição.
- Encerrar a requisição.
- Passar para o próximo middleware.
Por exemplo:
function authMiddleware(
request: Request,
next: () => void
) {
if (!request.user) {
throw new Error(
"Usuário não autenticado"
);
}
next();
}
Outro:
function loggingMiddleware(
request: Request,
next: () => void
) {
console.log(
`Request: ${request.url}`
);
next();
}
A ideia é a mesma:
Middleware A
↓
Middleware B
↓
Middleware C
↓
Controller
Quando usar?
Chain of Responsibility é útil quando:
- Existem vários objetos que podem processar uma requisição.
- A ordem de processamento importa.
- Queremos evitar muitos
if/else. - Queremos adicionar ou remover etapas facilmente.
Exemplos:
Middlewares HTTP
Sistemas de suporte
Validação
Processamento de eventos
Filtros
Autorização
Logging
A ideia principal é:
Passar uma requisição por uma cadeia de objetos até que ela seja processada.