2010年6月20日日曜日

Chain of Responsibilityパターン

Chain Of Responsibilityパターンは(本では)責任のたらい回しと書かれていて、なんだか悪いイメージがしますが、このパターンは「自分のところで処理できなければ、別の人に処理をお願いする」というパターンです。


今回もコードは単純に書きます(´・ω・`)
概要を先に示すと、
・クライアントはトラブルを対処する人にトラブル情報を渡す。
・トラブルを対処する人はトラブル情報を確認し、
・自分で対処できる→対処する
・自分で対処できない→他の人に対処してもらう
という感じです。トラブル情報は単純にトラブル番号のみを持つとします(本と同じです)


トラブルを対処するSupportクラスは以下のような感じです。
  1. public abstract class Support {  
  2.     ・・・  
  3.     private Support next;  
  4.     ・・・  
  5.     public Support(String name) {  
  6.          ・・・  
  7.     }  
  8.     publilc Support setNext(Support next) {  
  9.         this.next = next;  
  10.         return next;  
  11.     }  
  12.     public final void support(Trouble trouble) {  
  13.         if (resolve(trouble)) {  
  14.             // 解決できた時の処理を記述  
  15.         } else if (next != null) {  
  16.             // 次の人にお願いする。  
  17.             next.support(trouble);  
  18.         } else {  
  19.             // 次の人がいない(誰ひとりとして対処できなかった)時の処理を記述  
  20.         }  
  21.     }  
  22.     protected abstract boolean resolve(Trouble trouble);  
  23. }  
自分で対処できない場合に次の人にお願いするので、Supportクラスのインスタンスをnextフィールドで持つようにします。

対処する時にはsupportメソッドが呼ばれます。中ではまず、サブクラスで定義されるresolveメソッドを呼びます。resolveメソッドは解決できた時にtrue、解決できなかった時にfalseが返すとします。trueならば、解決できたのでその時の処理を実行し、そうでない場合は次の人(nextに入っているSupportクラスのインスタンス)にお願いします。そして、次の人でsupportメソッドが実行され、解決できた時はその時の処理、解決できなかったときは次の人へ・・・と処理が続きます。もし、解決できないまま、次の人がいなくなってしまった場合はそのトラブルは誰ひとりとして対処できなかったということで、その時の処理を実行します。

Supportクラスのサブクラスはresolveメソッドを実装します。Troubleクラスのインスタンスの中身を参照して、そのメソッドにあった処理を実装します。

Mainクラスでは対処順序を決めておき、出てきたトラブルを対処してもらいましょう(ちなみに、出てきたトラブルをSupportにお願いするのがクライアントの役目です)
  1. ・・・  
  2. Support support1 = new Support1(・・・);  
  3. Support support2 = new Support2(・・・);  
  4. Support support3 = new Support3(・・・);  
  5. support1.setNext(support2).setNext(support3);// 本当はJavaでメソッドチェーンを書くのはあまりおすすめしない・・・  
  6. ・・・  
  7. support1.support(new Trouble(・・・));  
このパターンの良いところは、クライアントはトラブル対処処理を知る必要がなく、1人目にお願いするだけで良いというところです。クライアントとサポートのつながりがゆるいということです。もし、クライアントがトラブル対処処理を知るとなると、密なつながりを持つことになってしまいます。

サポートだけを見ても、無理ならば次の人にお願いするだけなので、サポートメンバーを全員知っておく必要もありません。しかし、たらい回しなのでパフォーマンスが悪くなる可能性があるのがこのパターンの欠点です。もし、パフォーマンスを上げたければ、各サポートメンバーを知っているマネージャーがいて、トラブルの中身によって適切なサポートメンバーにお願いするという形になると思います。「このトラブルについてはこの人に任せよう」と直接お願いするということです。

関連パターン
Compositeパターン」サポートがCompositeパターンで定義される場合あり
「Commandパターン」(勉強中)

2 件のコメント: