PHP7でデザインパターン入門14/23 Chain of Responsibilityパターン

Chain of Responsibility パターンとは

Chain of Responsibility パターン - Wikipedia

一つの コマンドオブジェクトと一連の 処理オブジェクトから構成される。各処理オブジェクトは、処理できるコマンドオブジェクトの種類と、自身が処理できないコマンドオブジェクトをチェーン内の次の処理オブジェクトに渡す方法を記述する情報を保持する。また、新たな処理オブジェクトをチェーンの最後に追加する機構を備える

Chain of Responsibiliy(責任の連鎖) とは 責任の「たらい回し」であるとも言える。 このパターンを使うと要求する側と処理する側の結びつきを弱めることができ、それぞれを部品として独立させることができる。 また状況によって要求を処理するオブジェクトが変化するようなプログラムにも対応することができる。

要求が来る。その人が処理できるなら対応、できないなら次の人へたらい回しにする…処理に対応できるまでこれを繰り返す。これがChain of Responsibilityパターンである。

example

発生したトラブルを誰かが処理しなければならない状況を考える。

以下サンプルコード。

github.com

Troubleクラス

発生したトラブルを表現するクラス。numberはトラブル。getNumberでトラブル番号を得る。

Supportクラス

トラブルを解決する連鎖を作るための抽象クラス。 nextプロパティはたらい回しする先を指す。resolveメソッドはサブクラスで実装することを想定した抽象メソッド。supportメソッドはresolveメソッドを呼び出し戻り値がfalseなら次の人にたらい回しにする。

NoSupportクラス

Supportクラスのサブクラス。NoSupportクラスのresolveメソッドは常にfalseを返す。「自分は何も処理しない」というクラス

LimitSupportクラス

limitで指定した番号未満のトラブルを解決するクラス。

OddSupportクラス

奇数番号のトラブルを処理するクラス。

SpecialSupportクラス

指定した番号のトラブルに限って処理するクラス

Main

サンプルコード実行用

実行結果

$ php Main.php
[Trouble 0] is resolved by [Bob].
[Trouble 33] is resolved by [Bob].
[Trouble 66] is resolved by [Bob].
[Trouble 99] is resolved by [Bob].
[Trouble 132] is resolved by [Diana].
[Trouble 165] is resolved by [Diana].
[Trouble 198] is resolved by [Diana].
[Trouble 231] is resolved by [Elmo].
[Trouble 264] is resolved by [Fred].
[Trouble 297] is resolved by [Elmo].
[Trouble 330] cannot be resolved.
[Trouble 363] is resolved by [Elmo].
[Trouble 396] cannot be resolved.
[Trouble 429] is resolved by [Charlie].
[Trouble 462] cannot be resolved.
[Trouble 495] is resolved by [Elmo].

役割

Handler

Handler役は要求を処理するインターフェースを定める役。サンプルコードにおけるSuportクラス。

ConcreteHAndler

要求を処理する具体的な役。サンプルコードにおけるNoSupport, LimitSupport, OddSupport, SpecialSupportクラス。

Client

サンプルコードにおけるMainクラス。

まとめ

  • 要求を出す人と要求する人をゆるやかに結びつける
  • 動的に連鎖の形態を変える
  • たらい回し処理は遅くならないのか?
    • 要求する処理を誰が行うか決まっている場合に比べて遅くなる。

関連パターン

増補改訂版Java言語で学ぶデザインパターン入門

増補改訂版Java言語で学ぶデザインパターン入門