+TypeScript 예제
접수 코드는 첫 처리자에게 요청만 보내고, 각 처리자는 자기 담당인지 판단한다. 담당 선택을 접수 화면에서 분리해 처리 순서와 구성을 바꾸기 쉽게 만든다.
type Ticket = Readonly<{ kind: string }>;
type Reply = Readonly<{ handled: boolean; message: string }>;
// 담당 판단은 처리자에 두고, 넘기는 공통 흐름은 기반 클래스에서 공유한다.
abstract class Handler {
constructor(private readonly next: Handler | null) {}
handle(ticket: Ticket): Reply {
const reply = this.tryHandle(ticket);
if (reply !== null) return reply;
return this.next?.handle(ticket) ?? { handled: false, message: "unhandled: " + ticket.kind };
}
protected abstract tryHandle(ticket: Ticket): Reply | null;
}
// 담당이 아니면 다음 처리자를 선택하지 않고 null만 반환한다.
class BillingHandler extends Handler {
protected override tryHandle(ticket: Ticket): Reply | null {
return ticket.kind === "billing" ? { handled: true, message: "billing desk" } : null;
}
}
class TechHandler extends Handler {
protected override tryHandle(ticket: Ticket): Reply | null {
return ticket.kind === "technical" ? { handled: true, message: "technical desk" } : null;
}
}
const chain = new BillingHandler(new TechHandler(null));
for (const kind of ["billing", "technical", "other"]) {
const result = chain.handle({ kind });
console.log(result.handled + ": " + result.message);
}
true: billing desk
true: technical desk
false: unhandled: other
null은 현재 처리자가 맡지 않았다는 뜻이고, handled=false는 체인 끝의 최종 결과다. 이 예제는 처음 처리한 곳에서 멈춘다.