責任連鎖モデル


その名前が示すように、Chain of Responsibility パターンはリクエストの受信者オブジェクトのチェーンを作成します。このパターンはリクエストのタイプを示し、リクエストの送信者と受信者を分離します。このタイプの設計パターンは動作パターンです。


このパターンでは、通常、各受信者に別の受信者への参照が含まれます。オブジェクトがリクエストを処理できない場合は、同じリクエストを次の受信者に渡します。

はじめに

目的: リクエストの送信者と受信者の結合を回避し、複数のオブジェクトがリクエストを受信できるようにし、これらのオブジェクトをチェーンに接続し、オブジェクトが存在するまでこのチェーンに沿ってリクエストを渡します。それと。

主な解決策: 責任チェーン上のプロセッサは、リクエストを責任チェーンに送信するだけで済みます。リクエストの処理の詳細やリクエストの配信について気にする必要はありません。責任チェーンは、リクエストの送信者とリクエスト ハンドラーを結合します。リクエスト ハンドラーは分離されます。

いつ使用するか: メッセージを処理するときに多くのチャネルをフィルタリングするため。

解決方法: インターセプトされたすべてのクラスは、統合インターフェイスを実装します。

キーコード: HandlerはHanleRequest内で自身を集約し、条件が満たされない場合は誰に渡す前に引き継がれて設定されます。

応用例: 1. 紅楼夢の「太鼓をたたいて花を渡す」。 2. JS でのイベントのバブリング。 3. JAVA WEBのApache TomcatによるEncoding、Struts2のインターセプタ、jspサーブレットのFilterの処理。

利点: 1. カップリングを軽減します。これにより、リクエストの送信者と受信者が分離されます。 2. 単純化されたオブジェクト。オブジェクトはチェーンの構造を知る必要はありません。 3. オブジェクトに対する責任の割り当ての柔軟性を強化します。チェーン内のメンバーを変更したり、順序を移動したりすることで、責任を動的に追加または削除できます。 4. 新しいリクエスト処理クラスを追加すると非常に便利です。

欠点: 1. リクエストが受信されるという保証はありません。 2. システムのパフォーマンスにある程度の影響があり、コードのデバッグが不便になり、ループ呼び出しが発生する可能性があります。 3. 実行時の特性を観察することが難しく、デバッグに支障をきたす可能性があります。

使用シナリオ: 1. 複数のオブジェクトが同じリクエストを処理できます。どのオブジェクトがリクエストを処理するかは実行時に自動的に決定されます。 2. 受信者を明示的に指定せずに、複数のオブジェクトの 1 つにリクエストを送信します。 3. リクエストを処理するためにオブジェクトのグループを動的に指定できます。

注: JAVA WEB で多くのアプリケーションに遭遇しました。

実装

冗長ログレベルを持つ抽象クラスAbstractLoggerを作成します。次に、3 種類のロガーを作成します。これらはすべて AbstractLogger を拡張しています。各ロガー メッセージのレベルが独自のレベルに属するかどうか。そうである場合は、それに応じて出力されます。そうでない場合は出力されず、メッセージは次のロガーに渡されます。

chain_pattern_uml_diagram.jpg

ステップ 1

抽象ロガークラスを作成します。

AbstractLogger.java

public abstract class AbstractLogger {
   public static int INFO = 1;
   public static int DEBUG = 2;
   public static int ERROR = 3;

   protected int level;

   //责任链中的下一个元素
   protected AbstractLogger nextLogger;

   public void setNextLogger(AbstractLogger nextLogger){
      this.nextLogger = nextLogger;
   }

   public void logMessage(int level, String message){
      if(this.level <= level){
         write(message);
      }
      if(nextLogger !=null){
         nextLogger.logMessage(level, message);
      }
   }

   abstract protected void write(String message);
	
}

ステップ 2

このロガー クラスを拡張するエンティティ クラスを作成します。

ConsoleLogger.java

public class ConsoleLogger extends AbstractLogger {

   public ConsoleLogger(int level){
      this.level = level;
   }

   @Override
   protected void write(String message) {		
      System.out.println("Standard Console::Logger: " + message);
   }
}

ErrorLogger.java

public class ErrorLogger extends AbstractLogger {

   public ErrorLogger(int level){
      this.level = level;
   }

   @Override
   protected void write(String message) {		
      System.out.println("Error Console::Logger: " + message);
   }
}

FileLogger.java

public class FileLogger extends AbstractLogger {

   public FileLogger(int level){
      this.level = level;
   }

   @Override
   protected void write(String message) {		
      System.out.println("File::Logger: " + message);
   }
}

ステップ 3

さまざまなタイプのロガーを作成します。異なるエラー レベルを与え、各ロガー内で次のロガーを設定します。各ロガー内の次のロガーはチェーンの一部を表します。

ChainPatternDemo.java

public class ChainPatternDemo {
	
   private static AbstractLogger getChainOfLoggers(){

      AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
      AbstractLogger fileLogger = new FileLogger(AbstractLogger.DEBUG);
      AbstractLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO);

      errorLogger.setNextLogger(fileLogger);
      fileLogger.setNextLogger(consoleLogger);

      return errorLogger;	
   }

   public static void main(String[] args) {
      AbstractLogger loggerChain = getChainOfLoggers();

      loggerChain.logMessage(AbstractLogger.INFO, 
         "This is an information.");

      loggerChain.logMessage(AbstractLogger.DEBUG, 
         "This is an debug level information.");

      loggerChain.logMessage(AbstractLogger.ERROR, 
         "This is an error information.");
   }
}

ステップ 4

出力を確認します。

りー