チェーン・オブ・リスポンシビリティパターン
チェーン・オブ・リスポンシビリティパターン(Chain of Responsibility Pattern) は、リクエストを処理する複数のオブジェクトを連鎖させ、リクエストが処理されるまで次のオブジェクトに渡すことで、処理の流れを柔軟に管理するデザインパターンです。このパターンでは、リクエストの送信者と受信者を分離し、柔軟な処理の分担を実現します。
このパターンは、複数の処理者が順番にリクエストを処理する必要がある場合に有効です。例えば、カスタマーサポートの問い合わせに対して、複数の担当者が段階的に対応する場合などに使われます。
TypeScriptでのチェーン・オブ・リスポンシビリティパターンの実装
以下に、TypeScriptでチェーン・オブ・リスポンシビリティパターンを実装する例を紹介します。この例では、異なるレベルのリクエスト(「低レベル」「中レベル」「高レベル」)を処理するハンドラーをチェーンでつなげて実装します。
リクエストハンドラーの例
typescript
// ハンドラーインターフェース
interface Handler {
setNext(handler: Handler): Handler;
handle(request: string): void;
}
// 抽象ハンドラークラス
abstract class AbstractHandler implements Handler {
private nextHandler: Handler | null = null;
setNext(handler: Handler): Handler {
this.nextHandler = handler;
return handler;
}
handle(request: string): void {
if (this.nextHandler) {
this.nextHandler.handle(request);
}
}
}
// 具体的なハンドラークラス(低レベルのリクエストを処理)
class LowLevelHandler extends AbstractHandler {
handle(request: string): void {
if (request === 'Low') {
console.log('LowLevelHandler is handling the request.');
} else {
super.handle(request);
}
}
}
// 具体的なハンドラークラス(中レベルのリクエストを処理)
class MidLevelHandler extends AbstractHandler {
handle(request: string): void {
if (request === 'Mid') {
console.log('MidLevelHandler is handling the request.');
} else {
super.handle(request);
}
}
}
// 具体的なハンドラークラス(高レベルのリクエストを処理)
class HighLevelHandler extends AbstractHandler {
handle(request: string): void {
if (request === 'High') {
console.log('HighLevelHandler is handling the request.');
} else {
super.handle(request);
}
}
}
// 実際の使用例
const lowLevelHandler = new LowLevelHandler();
const midLevelHandler = new MidLevelHandler();
const highLevelHandler = new HighLevelHandler();
lowLevelHandler.setNext(midLevelHandler).setNext(highLevelHandler);
console.log('Request: Low');
lowLevelHandler.handle('Low');
console.log('\nRequest: Mid');
lowLevelHandler.handle('Mid');
console.log('\nRequest: High');
lowLevelHandler.handle('High');
console.log('\nRequest: Unknown');
lowLevelHandler.handle('Unknown');
解説
Handlerインターフェース
Handler
インターフェースは、次のハンドラーを設定するsetNext
メソッドと、リクエストを処理するためのhandle
メソッドを定義しています。
AbstractHandlerクラス(抽象ハンドラー)
AbstractHandler
クラスは、Handler
インターフェースを実装し、次のハンドラーを設定する機能を提供します。handle
メソッドで、次のハンドラーにリクエストを渡す処理を実装しています。
具体的なハンドラークラス(LowLevelHandler、MidLevelHandler、HighLevelHandler)
LowLevelHandler
、MidLevelHandler
、HighLevelHandler
は、具体的なリクエストを処理するハンドラークラスです。それぞれが特定のリクエスト(「低レベル」「中レベル」「高レベル」)を処理し、処理できない場合は次のハンドラーにリクエストを渡します。
実際の使用例
LowLevelHandler
、MidLevelHandler
、HighLevelHandler
をチェーンでつなぎ、リクエストが適切なハンドラーで処理されるようにします。リクエストが処理されない場合は、次のハンドラーに渡され、最終的に適切なハンドラーがリクエストを処理します。
利点
- 柔軟なリクエスト処理: リクエストを複数のハンドラーに渡すことができるため、処理の流れを柔軟に管理できます。
- オープン/クローズド原則の遵守: 新しいハンドラーを追加することで、既存のコードを変更せずに処理を拡張できます。
- 疎結合の実現: リクエストの送信者と受信者を分離することで、クライアントコードと処理コードの結合度を下げ、保守性を向上させます。
使用例
- カスタマーサポートシステム: 顧客からの問い合わせが、まずはオペレーターに渡され、解決できない場合はマネージャーにエスカレーションされる、といった処理で使用されます。
- ログシステム: ログメッセージを適切なレベル(デバッグ、情報、エラー)に基づいて異なるハンドラーで処理する際に使います。
- イベント処理: ユーザーインターフェースのイベント処理において、イベントが適切なハンドラーに渡されるまでチェーンで処理を行う場合に使用されます。
まとめ
チェーン・オブ・リスポンシビリティパターンは、リクエストの処理を複数のハンドラーで順番に処理するためのデザインパターンです。TypeScriptでの実装を通じて、リクエストを柔軟に処理し、コードの保守性と拡張性を向上させる方法を理解できました。
このパターンを利用することで、リクエストの処理の流れを柔軟に変更したり、ハンドラーを追加して処理を拡張することが容易になり、複雑なシステムでもシンプルに管理することが可能です。