23種類の設計モード(19)java責任連鎖モード


23種類の設計モードの第19編:java責任連鎖モード
定義:複数のオブジェクトが要求を処理する機会を与え、要求の送信者と受信者との間の結合関係を回避する。これらのオブジェクトをチェーンに接続し、オブジェクトがそれを処理するまで、このチェーンに沿って要求を伝達する。
タイプ:行動パターン
クラス図:

まずコードを見てみます。

public void test(int i, Request request){ 
  if(i==1){ 
    Handler1.response(request); 
  }else if(i == 2){ 
    Handler2.response(request); 
  }else if(i == 3){ 
    Handler3.response(request); 
  }else if(i == 4){ 
    Handler4.response(request); 
  }else{ 
    Handler5.response(request); 
  } 
}
コードのトラヒックロジックは、2つのパラメータがあります。整数iと要求requestは、iの値に基づいてrequestを処理する人を決定します。i=1なら、Handler 1で処理します。i=2なら、Handler 2で処理します。
プログラミングでは、このような処理方法はよく見られます。すべての処理要求の種類はif...else...条件判定文が一つの責任連鎖となって要求を処理します。この方法の利点は非常に直観的で分かりやすく、メンテナンスしやすいですが、この方法にはいくつかの比較的難しい問題があります。
コード肥大:実際のアプリケーションでの判定条件は通常、1か2かを簡単に判断するのではなく、複雑な計算が必要かもしれません。データベースなどを調べる必要があるかもしれません。
結合度が高い:もし処理要求のクラスを追加したいなら、引き続きelse if判定条件を追加します。また、この条件で判定する順番も死ぬので、順番を変えたいなら、この条件文を修正するしかないです。
        欠点がわかった上は、何とかして解決します。このシーンの業務ロジックは簡単です。条件1を満たすなら、Handler 1で処理します。満足しないなら、下に転送します。条件2が満たされていれば、Handler 2によって処理され、満たされていない場合は、条件が終了するまで下に伝達され続ける。実は改善の方法もとても簡単です。判定条件の部分を処理類に置くということです。これは責任連モードの原理です。
責任連鎖パターンの構造
        責任連鎖パターンの類図は非常に簡単で、クラスを抽象的に処理し、そのグループの実現クラスから構成される。
抽象的な処理クラス:抽象的な処理クラスは主に次の処理クラスを指すメンバー変数nextHandlerと一つの処理要求の方法handRequestとhandRequestを含んでいます。
具体的な処理の種類:具体的な処理の種類は主に具体的な処理の論理と処理の適用条件に対して実現を行います。
責任連鎖パターンの基本思想を理解してからコードを見れば分かりやすいです。

class Level { 
    private int level = 0; 
    public Level(int level){ 
      this.level = level; 
    }; 
     
    public boolean above(Level level){ 
      if(this.level >= level.level){ 
        return true; 
      } 
      return false; 
    } 
  } 
   
  class Request { 
    Level level; 
    public Request(Level level){ 
      this.level = level; 
    } 
     
    public Level getLevel(){ 
      return level; 
    } 
  } 
   
  class Response { 
   
  } 
   
  abstract class Handler { 
    private Handler nextHandler;   
    public final Response handleRequest(Request request){ 
      Response response = null; 
       
      if(this.getHandlerLevel().above(request.getLevel())){ 
        response = this.response(request); 
      }else{ 
        if(this.nextHandler != null){ 
          this.nextHandler.handleRequest(request); 
        }else{ 
          System.out.println("-----        -----"); 
        } 
      } 
      return response; 
    } 
    public void setNextHandler(Handler handler){ 
      this.nextHandler = handler; 
    } 
    protected abstract Level getHandlerLevel(); 
    public abstract Response response(Request request); 
  } 
   
  class ConcreteHandler1 extends Handler { 
    protected Level getHandlerLevel() { 
      return new Level(1); 
    } 
    public Response response(Request request) { 
      System.out.println("-----      1    -----"); 
      return null; 
    } 
  } 
   
  class ConcreteHandler2 extends Handler { 
    protected Level getHandlerLevel() { 
      return new Level(3); 
    } 
    public Response response(Request request) { 
      System.out.println("-----      2    -----"); 
      return null; 
    } 
  } 
   
  class ConcreteHandler3 extends Handler { 
    protected Level getHandlerLevel() { 
      return new Level(5); 
    } 
    public Response response(Request request) { 
      System.out.println("-----      3    -----"); 
      return null; 
    } 
  } 
   
  public class Client { 
    public static void main(String[] args){ 
      Handler handler1 = new ConcreteHandler1(); 
      Handler handler2 = new ConcreteHandler2(); 
      Handler handler3 = new ConcreteHandler3(); 
   
      handler1.setNextHandler(handler2); 
      handler2.setNextHandler(handler3); 
       
      Response response = handler1.handleRequest(new Request(new Level(4))); 
    } 
  }
コードの中のレベルはアナログ判定条件です。Request、Reponseはそれぞれ要求と応答に対応する。抽象的な種類のHandlerでは、主に条件の判断を行います。ここで処理レベルをシミュレーションします。処理クラスの処理レベルがRequestより高い等級しか処理できません。そうでなければ、次の処理者に任せます。
Clientクラスでチェーンの前後実行関係を設定し、実行時に要求を最初の処理クラスに渡す。これは責任チェーンモードであり、完成した機能は前の文のif...else...文と同じである。
責任連鎖モデルの長所と短所
        責任連鎖パターンはif…else…に比べて、彼の結合性は低く、条件判定を各処理クラスに分散させ、これらの処理類の優先処理順序は任意に設定できるからである。責任連鎖モードにも欠点があります。これはif...else...文の欠点と同じです。正しい処理クラスを見つける前に、すべての判定条件をもう一度実行します。
責任連鎖モードの適用シーン
       最初の例のように、if...else...という言葉を使って、責任連鎖を作った時に、力が足りなくて、コードが悪く見えた時に、責任連鎖モードを使って再構成することができます。
締め括りをつける
       このような判定条件の語句を各処理類に置いたのです。このようにする利点は柔軟性がありますが、処理類の前後関係を設定する時には、必ず注意しないでください。処理類の前後論理的条件判断関係を作ります。また、チェーンに循環参照の問題が現れないように注意してください。
以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。