Chain of Responsibilityパターンの解説

Chain of Responsibilityパターンとは、複数のオブジェクトに対して処理を順番に回していくデザインパターンだ。これにより、どのオブジェクトが処理を担当するかを動的に決めることができる。

たとえば、ゲームでプレイヤーの行動に応じて、複数のシステムが順番に対応するようにする場合に使える。

では、サンプルコードを一緒に見ていこう。

解説

たとえば、君が何か困ったことを先生に相談すると、先生が答えられないときは別の先生に相談することがあるよね。このように、順番に誰かが対応する仕組みを「Chain of Responsibility パターン」と呼ぶんだ。

Step 1: ハンドラー(処理者)を定義する

まず、問題を処理する人(ハンドラー)を作る。ハンドラーには、自分で問題を解決できないとき、次の人に問題を渡す仕組みを作る。


// ハンドラーの基本クラス
class Handler {
  constructor() {
    this.nextHandler = null;
  }

  setNext(handler) {
    this.nextHandler = handler;
  }

  handle(request) {
    if (this.nextHandler) {
      return this.nextHandler.handle(request);
    } else {
      console.log("誰もこのリクエストを処理できませんでした");
    }
  }
}
      

Step 2: 具体的な処理者を作成する

次に、具体的な処理者を作る。それぞれの処理者が、自分に対するリクエストを処理できるか判断し、できない場合は次の処理者に渡すようにする。


// 小さなリクエストを処理するハンドラー
class SmallRequestHandler extends Handler {
  handle(request) {
    if (request <= 10) {
      console.log("小さなリクエストを処理しました: " + request);
    } else {
      super.handle(request);
    }
  }
}

// 中くらいのリクエストを処理するハンドラー
class MediumRequestHandler extends Handler {
  handle(request) {
    if (request > 10 && request <= 50) {
      console.log("中くらいのリクエストを処理しました: " + request);
    } else {
      super.handle(request);
    }
  }
}

// 大きなリクエストを処理するハンドラー
class LargeRequestHandler extends Handler {
  handle(request) {
    if (request > 50) {
      console.log("大きなリクエストを処理しました: " + request);
    } else {
      super.handle(request);
    }
  }
}
      

Step 3: ハンドラーをチェーンにする

それぞれの処理者(ハンドラー)を順番に連結して、どれかがリクエストを処理できるまで次々に渡していく仕組みを作る。


// ハンドラーをチェーンにする
const smallHandler = new SmallRequestHandler();
const mediumHandler = new MediumRequestHandler();
const largeHandler = new LargeRequestHandler();

smallHandler.setNext(mediumHandler);
mediumHandler.setNext(largeHandler);
      

Step 4: リクエストを処理してみる

最後に、リクエストを処理者に渡してみる。それぞれの処理者がリクエストを処理できるか確認し、できなければ次の処理者に渡す。


// リクエストを処理してみる
smallHandler.handle(5);   // 結果: 小さなリクエストを処理しました: 5
smallHandler.handle(30);  // 結果: 中くらいのリクエストを処理しました: 30
smallHandler.handle(100); // 結果: 大きなリクエストを処理しました: 100
      

Chain of Responsibilityパターンの重要なポイント

これでChain of Responsibilityパターンの解説は終わりだ。
このパターンを使うと、処理を複数のオブジェクトに分担させ、柔軟に対応できるため、動的な処理フローが必要な場面に適している。