Design Patterns - Chain of Responsibility Patterns (17)

definition

The Chain of Responsibility Pattern is a common behavior pattern.

责任链模式英文原话是:Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request.Chain the receiving object and pass the request along the chain until an object handles it.

Translation: Make multiple objects have the opportunity to process the request, thereby avoiding the coupling relationship between the sender and receiver of the request. String these objects into a chain and pass the request along the chain until an object handles it.

The focus of the Chain of Responsibility model is "on the chain", where a chain handles similar requests, decides who handles the request in the chain, and returns the corresponding result.

Role:

Abstract Handler role: This role abstracts the request and defines a method to set and return a reference to the next handler.

Concrete Handler: After receiving the request, the role can choose to process the request or pass the request to the next handler. Since a concrete handler holds a reference to the next handler, the handler can access the next handler if needed.

/**
 * Abstract handler
 */ 
public  abstract  class Handler {
     // Next handler 
    private Handler nextHandler;

    // Handling method 
    public  abstract  void handleRequest();

    public Handler getNextHandler() {
        return nextHandler;
    }
    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }
}

/**
 * Specific processor.
 */
public class ConcreteHandler extends Handler {

    @Override
    public void handleRequest() {
        System.out.println( this .toString()+"handler processing" );
         if (getNextHandler()!= null ){    // Determine whether there is a next handler 
            getNextHandler().handleRequest();    // If it exists call next handler 
        }
    }

}

/**
 * test
 */
public class Client {
    public static void main(String[] args) {
        Handler h1 = new ConcreteHandler();
        Handler h2 = new ConcreteHandler();
        h1.setNextHandler(h2);    // h1's next handler is h2 
        h1.handleRequest();
    }
}

source code

advantage

  • The chain of responsibility model separates the request and the processing. The requester does not know who handled it, and the processor does not need to know the full picture of the request.
  • Improve system flexibility.

shortcoming

  • Reduce program performance. Each request is traversed from the head of the chain to the tail of the chain. When the chain is relatively long, the performance will drop significantly.
  • Not easy to debug. Since this mode adopts a recursive-like way, the logic during debugging is more complicated.

Application scenarios

The chain of responsibility mode is a common mode. The core control of Struts2, FilterDispatcher, is a servlet filter. This control adopts the chain of responsibility mode, which can filter user requests layer by layer. The chain of responsibility model is widely used in actual projects, and its typical application scenarios are as follows:

  • A request requires a series of processing work.
  • The processing of business flows, such as document approval.
  • Expand the system.
/**
 * Abstract handler.
 */ 
public  abstract  class AbstractLogger {
     public  static  final  int INFO = 1;     // Level 1 log 
    public  static  final  int DEBUG = 2;    // Level 2 log includes Level 1 
    public  static  final  int ERROR = 3;    // Level 3 includes before two

    protected  int level;
     // The next element of the chain of responsibility 
    protected AbstractLogger nextLogger ;
     public  void setNextLogger(AbstractLogger nextLogger){
         this .nextLogger = nextLogger;
    }

    // The recording methods of different levels are different, here is an abstract recording method 
    abstract  protected  void write(String message);

    // Call the record method of the responsibility chain processor. And judge whether the next responsibility chain element exists, if so, execute the next method. 
    public  void logMessage( int level, String message){
         if ( this .level <= level) {     // According to the incoming log level, determine which chain of responsibility elements are to be recorded 
            write(message);
        }
        if (nextLogger != null){
            nextLogger.logMessage(level,message);    // Process the next responsibility chain element 
        }
    }
}

/**
 * Console handler.
 */
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);
    }
}

/**
 * File handler.
 */
public class FileLogger extends AbstractLogger {
    public FileLogger(int level) {
        this.level = level;
    }

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

/**
 * error log handler.
 */
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);
    }
}

/**
 * Processing chain.
 */
public class ChainPatternDemo {

    public 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 class Main {
    public static void main(String[] args) {
        AbstractLogger logger = ChainPatternDemo.getChainOfLoggers();
        logger.logMessage( 1, "First-level logging" );
        System.out.println("--------------------------------");
        logger.logMessage( 2,"Secondary Logging" );
        System.out.println("--------------------------------");
        logger.logMessage( 3, "Level 3 logging" );
    }
}

  source code

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324574675&siteId=291194637