Java設計モード(14)責任チェーンモード(Chain of Responsibilityモード)


Chain of Responsibility定義:Chain of Responsibility(CoR)は、要求requestを一連のクラス(classes)で処理しようとするが、これらのクラス間は緩やかな結合であり、唯一の共通点は彼らの間でrequestを伝達することである.すなわち,要求が来て,Aクラスが先に処理し,処理しなければBクラスに処理し,処理しなければCクラスに処理し,そのままチェーンのように伝達する.
責任チェーン・モードの使用方法
この段落ではCoRの使い方を説明しますが、CoRとは何かを示しています.Handlerインタフェースがあります.
public interface Handler{

  public void handleRequest();

}

これはrequestを処理する例で、ヘルプリクエストの印刷やフォーマットなどのrequestが複数ある場合です.◆最初に思いついた解決策は、インタフェースに複数のリクエストを追加することです.
public interface Handler{

  public void handleHelp();

  public void handlePrint();

  public void handleFormat();

}

具体的には、実装インタフェースHandlerコード:
public class ConcreteHandler implements Handler{

  private Handler successor;

  public ConcreteHandler(Handler successor){

          this.successor=successor;

        }



  public void handleHelp(){

    //      Help   

    ...

  }



  public void handlePrint(){

    //   print     Print

    successor.handlePrint();

  }

  public void handleFormat(){

    //   Format     format

    successor.handleFormat();

  }



}

このような具体的な実装クラスは全部で3つあります.上にはhelpを処理し、Printを処理してFormatを処理することがあります.これはおそらく私たちが最もよく使うプログラミングの考え方です.
考え方は簡単明瞭であるが,要求requestの種類をもう一つ追加する必要がある場合は,インタフェースとその各実装を修正する必要がある拡張問題がある.◆第2のシナリオ:各requestを1つのインタフェースにするため、次のコードがあります.
public interface HelpHandler{

  public void handleHelp();

}



public interface PrintHandler{

  public void handlePrint();

}



public interface FormatHandler{

  public void handleFormat();

}



public class ConcreteHandler

  implements HelpHandler,PrintHandler,FormatHandlet{

  private HelpHandler helpSuccessor;

  private PrintHandler printSuccessor;

  private FormatHandler formatSuccessor;



  public ConcreteHandler(HelpHandler helpSuccessor,PrintHandler printSuccessor,FormatHandler             formatSuccessor)

  {

    this.helpSuccessor=helpSuccessor;

    this.printSuccessor=printSuccessor;

    this.formatSuccessor=formatSuccessor;

  }



  public void handleHelp(){

    .......

  }



  public void handlePrint(){this.printSuccessor=printSuccessor;}



  public void handleFormat(){this.formatSuccessor=formatSuccessor;}



}

この方法は新しいリクエストrequestを追加する場合,インタフェースの修正量を節約するだけで,インタフェース実装ConcreteHandlerには修正が必要である.そしてコードは明らかに簡単ではありません.
◆ソリューション3:Handlerインタフェースでは1つのパラメトリックメソッドしか使用しません.
public interface Handler{

  public void handleRequest(String request);

}

  Handler      :



public class ConcreteHandler implements Handler{

  private Handler successor;



  public ConcreteHandler(Handler successor){

    this.successor=successor;

  }



  public void handleRequest(String request){

    if (request.equals("Help")){

      //     Help     

    }else

      //      

      successor.handle(request);



    }

  }



}

ここでrequestがStringタイプだと仮定しますが、そうでなければどうしますか?もちろん、インタフェースHandlerのコードは次のとおりです.
public interface Handler{

  public void handleRequest(Request request);

}

Request    :



public class Request{

  private String type;



  public Request(String type){this.type=type;}



  public String getType(){return type;}



  public void execute(){

    //request        

  }

}

ではHandler実装コードは次のようになります.
public class ConcreteHandler implements Handler{

  private Handler successor;



  public ConcreteHandler(Handler successor){

    this.successor=successor;

  }



  public void handleRequest(Request request){

    if (request instanceof HelpRequest){

      //     Help     

    }else if (request instanceof PrintRequst){

      request.execute();

    }else

      //      

      successor.handle(request);



    }

  }



}

このソリューションはCoRであり、1つのチェーンには対応する職責のクラスがあるため、Chain of Responsibilityと呼ばれています.
  • CoRの利点:外部からのリクエストがどのタイプに属するか予知できないため、各クラスが処理できないリクエストに遭遇したら放棄すればよい.これはクラス間の結合性を低下させるに違いない.
  • CoRの欠点は、1つのリクエストの完了が最終的に完了する可能性があるため、効率が低いことです.もちろん、ツリーの概念で最適化することもできます.Java AWT 1.0では,マウスボタンの件に対する処理はCoRを用いてJavaに至る.1.1以降、CoRの代わりにObserverを使用する.

  • 拡張性が悪いのは、CoRには必ず統一的なインターフェースHandlerがあるからだ.限界はここにある.
    シリーズ記事:
    Java設計モード(1)ファクトリモード(Factoryモード)
    Java設計モード(2)ワンストップモード(Singletonモード)
    Java設計モード(3)ビルダーモード(Builderモード)
    Java設計モード(4)プロトタイプモード(Prototypeモード)
    Java設計モード(5)共有モード/享元モード(Flyweightモード)
    Java設計モード(6)ブリッジモード(Bridgeモード)
    Javaデザインモード(7)デコレーションモード(Decoratorモード)
    Java設計モード(8)コンビネーションモード(Compositeモード)
    Java設計モード(9)アダプタモード(Adapterモード)
    Java設計モード(10)エージェントモード(Proxyモード)
    Javaデザインモード(11)外観モード(Facadeモード)
    Java設計モード(12)反復モード(Iteratorモード)
    Java設計モード(13)テンプレートモード(Templateモード)
    Java設計モード(14)責任チェーンモード(Chain of Responsibilityモード)
    Javaデザインモード(15)メモモード(Mementoモード)
    Java設計モード(16)仲介モード(Mediatorモード)
    Java設計モード(17)インタプリタモード(Interpreterモード)
    Java設計モード(18)ポリシーモード(Strategyモード)
    Java設計モード(19)状態モード(Stateモード)
    Java設計モード(20)オブザーバーモード(Observerモード)
    Java設計モード(21)アクセスモード(Visitor者モード)
    Java設計モード(22)コマンドモード(Commandモード)