책임 사슬 모델


이름에서 알 수 있듯이 책임 체인 패턴은 요청에 대한 수신자 개체 체인을 생성합니다. 이 패턴은 요청 유형을 제공하고 요청의 발신자와 수신자를 분리합니다. 이러한 유형의 디자인 패턴은 행동 패턴입니다.


이 패턴에서는 일반적으로 각 수신기에 다른 수신기에 대한 참조가 포함됩니다. 객체가 요청을 처리할 수 없는 경우 동일한 요청을 다음 수신자에게 전달합니다.

Introduction

의도: 요청 발신자와 수신자의 결합을 피하고, 여러 개체가 요청을 받을 수 있도록 하고, 이러한 개체를 체인으로 연결하고, 개체가 있을 때까지 이 체인을 따라 요청을 전달합니다. 그것으로.

주요 솔루션: 책임 체인의 처리자는 요청 처리를 담당합니다. 고객은 요청 처리 세부 사항과 요청 전달에 신경 쓸 필요가 없습니다. 책임 체인은 요청 보낸 사람을 요청 핸들러와 결합합니다.

사용 시기: 메시지를 처리할 때 여러 채널을 필터링합니다.

해결 방법: 가로채는 모든 클래스는 통합 인터페이스를 구현합니다.

키 코드: Handler는 HanleRequest에 자체적으로 집계하여 조건이 충족되지 않으면 누구에게 전달하기 전에 전달되고 설정됩니다.

적용 예: 1. 빨간 저택의 꿈에서 "북을 치며 꽃을 지나갑니다". 2. JS에서 이벤트 버블링. 3. JAVA WEB의 Apache Tomcat에 의한 인코딩 처리, Struts2의 인터셉터 및 jsp 서블릿의 필터.

장점: 1. 요청의 발신자와 수신자를 분리합니다. 2. 단순화된 객체. 객체는 체인의 구조를 알 필요가 없습니다. 3. 객체에 책임을 할당하는 유연성을 강화합니다. 체인 내 구성원을 변경하거나 순서를 이동하여 책임을 동적으로 추가하거나 삭제할 수 있습니다. 4. 새로운 요청 처리 클래스를 추가하는 것이 매우 편리합니다.

단점: 1. 요청이 수신된다는 보장이 없습니다. 2. 시스템 성능은 어느 정도 영향을 받게 되며, 코드를 디버깅하는 것이 불편하여 루프 호출이 발생할 수 있습니다. 3. 런타임 특성을 관찰하기 어려울 수 있으며, 이는 디버깅을 방해합니다.

사용 시나리오: 1. 여러 개체가 동일한 요청을 처리할 수 있습니다. 요청을 처리하는 개체는 런타임에 자동으로 결정됩니다. 2. 수신자를 명시적으로 지정하지 않고 여러 개체 중 하나에 요청을 제출합니다. 3. 요청을 처리하기 위해 개체 그룹을 동적으로 지정할 수 있습니다.

참고: JAVA WEB에서 많은 애플리케이션을 접했습니다.

Implementation

우리는 자세한 로깅 수준을 사용하여 추상 클래스 AbstractLogger를 생성합니다. 그런 다음 모두 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단계

출력을 확인합니다.

rreee