Chain of Responsibility (ChainOfResponsibility) mode

  In the chain of responsibility pattern, many objects of each object reference to them at home and connected together to form a chain. In this chain transfer request until a certain object on the chain determination process request. Requesting client does not know which object in the chain, which chain can reorganize the system so that the allocation of responsibilities and dynamically without affecting the client.

 

1. Starting from the flower drum transfer

  Flower drum transfer is a lively and tense game. In the banquet guests in turn seated position, drumming by one person, and the place where the drumming mass of flowers are separate, to show impartiality. Drumming at the start, it began to turn bouquet delivery, drums of a fall, if bouquet in the hands of a person, that person would have to drink.

  For example, Grandmother Jia, Jia She, Jia Jia Huan and five were spent participating in mass flower drum pass of the game, they formed a chain. Drumming will take to pass Grandmother Jia, start game of pass. Flowers are jiamu Jia She passed by Jia She JiaZheng passed by the pass Jia Zheng Jia, and Jia Jia Huan pass, pass back to the Jia Huan Jia Mu, and so forth, as shown in FIG. When the drums stop, the hands of people have to spend Drinking execution.

 

  Application of chain of responsibility pattern flower drum transfer is. Responsibility may be part of a straight chain, a chain or a tree structure.

2. The structure of chain of responsibility pattern

Roles involved are as follows:

Abstracting role: define an interface to a processing request. If desired, the interface may define a method to set and returns a reference to the next handler.

Specifically address this role: the role of the receipt of the request, the request may choose to dispose of or transfer the request to the next home.

 

code show as below:

Abstract handler:

public abstract class AbstractHandler {

    protected AbstractHandler nextHandler;

    public abstract void handleRequest();

    public AbstractHandler getNextHandler() {
        return nextHandler;
    }

    public void setNextHandler(AbstractHandler nextHandler) {
        this.nextHandler = nextHandler;
    }

}

 

Specific Processor: If you have at home is next to the home, otherwise deal with their own.

public  class ConcreteHandler the extends AbstractHandler { 

    @Override 
    public  void the handleRequest () {
         IF (getNextHandler () =! null ) { 
            System.out.println ( "to the next processor" ); 
            getNextHandler () the handleRequest ();. 
        } the else { 
            System.out.println ( "their process" ); 
        } 
    } 

}

 

Client code:

public class Client {
    public static void main(String[] args) {
        AbstractHandler handler1 = new ConcreteHandler();
        AbstractHandler handler2 = new ConcreteHandler();

        handler1.setNextHandler(handler2);
        handler1.handleRequest();
    }
}

 

  This logic is very simple example, there are at home is passed to the next house, not on the handling of requests themselves.

3. pure and impure chain of responsibility pattern

  A pure chain of responsibility model requires a specific handler object can only choose one of two acts: First, take responsibility, and second, passing the buck to the next house. Situation on a specific handler objects bear part of the responsibility and then pass down the responsibility not allowed.

  Pure inside a chain of responsibility pattern, a request must be processed by one object is received; impure inside a chain of responsibility pattern, a request may not ultimately be received by any receiver-side object.

  Practical examples of pure chain of responsibility pattern is difficult to find examples are generally seen to achieve impure chain of responsibility pattern. Some people think impure chain of responsibility is not a chain of responsibility pattern, this may be justified. But in the actual system, pure chain of responsibility is difficult to find. If you adhere to the chain of responsibility would not impure chain of responsibility pattern, then the chain of responsibility pattern will not have much meaning.

 

4. Chain of Responsibility pattern of application - Logger

     We created an abstract class  AbstractLogger , with detailed logging level. We then create three types of recorders, we have expanded  AbstractLogger . Each level recorder whether the message of their own level, and if the corresponding printed out, otherwise it will not print and forward the message to the next recorder.

Structured as follows:

 

(1) impure chain of responsibility pattern

public abstract class AbstractLogger {

    public static int DEBUG = 7;
    public static int INFO = 6;
    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);
        }
    }

    public abstract void write(String message);

}

 

public class DebugLogger extends AbstractLogger {

    public DebugLogger() {
        this.level = AbstractLogger.DEBUG;

        this.setNextLogger(new InfoLogger());
    }

    @Override
    public void write(String message) {
        System.out.println("DebugLogger message - > " + message);
    }

}

 

public class InfoLogger extends AbstractLogger {

    public InfoLogger() {
        this.level = AbstractLogger.INFO;

        this.setNextLogger(new ErrorLogger());
    }

    @Override
    public void write(String message) {
        System.out.println("InfoLogger message - > " + message);
    }

}

 

public class ErrorLogger extends AbstractLogger {

    public ErrorLogger() {
        this.level = AbstractLogger.ERROR;

    }

    @Override
    public void write(String message) {
        System.out.println("ErrorLogger message - > " + message);        
    }

}

 

Client code:

public class Client {

    public static void main(String[] args) {
        AbstractLogger logger = new DebugLogger();

        AbstractLogger logger2 = new ErrorLogger();

        String msg = "测试日志";
        int level = AbstractLogger.INFO;

        logger.logMessage(level, msg);
        System.out.println("=======");
        logger2.logMessage(level, msg);
    }

}

result:

InfoLogger message -> test log
ErrorLogger message -> test log
=======
ErrorLogger message -> test log

 

(2) Pure chain of responsibility pattern

  The above logging is impure, since InfoLogger had been recorded, and therefore do not need to pass the ErrorLogger, modified abstract processor, processed stop if:

public abstract class AbstractLogger {

    public static int DEBUG = 7;
    public static int INFO = 6;
    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);
            return;
        }

        if (nextLogger != null) {
            nextLogger.logMessage(level, message);
        }
    }

    public abstract void write(String message);

}

 

Re-run the client code, the following results:

InfoLogger message -> test log
=======
ErrorLogger the Message -> test log

 

5. Chain of Responsibility pattern evolution (actual responsibility chain mode usage)

  Chain of Responsibility pattern above said generally impure chain of responsibility pattern, so Chain of Responsibility pattern after the processor is to maintain a chain of evolution (internal maintains a set of storage processors), and in order to process the request (in the order set by maintenance chain relationship), as follows simulate the servlet filter filters:

Filter type:

public interface Filter {

    void doFilter(FilterChain filterChain);
}

 

public class LoginFilter implements Filter {

    @Override
    public void doFilter(FilterChain filterChain) {
        System.out.println("LoginFilter 开启运行");

        filterChain.doFilter();
    }

}

 

public class EncodeFilter implements Filter {

    @Override
    public void doFilter(FilterChain filterChain) {
        System.out.println("EncodeFilter 开启运行");

        filterChain.doFilter();
    }

}

 

public class OtherFilter implements Filter {

    @Override
    public void doFilter(FilterChain filterChain) {
        System.out.println("OtherFilter 开启运行");

        filterChain.doFilter();
    }

}

 

Processor chain:

public interface FilterChain {

    void doFilter();
}

 

import java.util.ArrayList;
import java.util.List;

public class PlainFilterChain implements FilterChain {

    private List<Filter> list = new ArrayList<>();

    private int index = 0;

    public PlainFilterChain add(Filter filter) {
        this.list.add(filter);
        return this;
    }

    public void doFilter() {
        if (index == list.size()) {
            return; // 处理完成之后就返回
        }

        F the Filter = List.get (index); // filter chain in order to get the index of the filter 
        index ++ ; 
        f.doFilter ( the this ); 
    } 
}

 

Client code:

public class Client {

    public static void main(String[] args) {
        Filter loginFilter = new LoginFilter();
        Filter encodeFilter = new EncodeFilter();
        Filter otherFilter = new OtherFilter();

        PlainFilterChain filterChain = new PlainFilterChain();
        filterChain.add(loginFilter);
        filterChain.add(encodeFilter);
        filterChain.add(otherFilter);

        filterChain.doFilter();
    }

}

result:

LoginFilter open run
EncodeFilter open run
OtherFilter open run

 

6. Summary

It is intended to: avoid requesting the sender and receiver are coupled together, so that a plurality of objects are likely to receive a request to connect these objects form a chain, and the request is transmitted along the chain until an object handles it so far.

: Mainly to solve the handler handler on duty chain responsible for handling requests, customers only need to send a request to transfer details of the treatment and the chain of responsibility can, without concern for the request of the request, so the chain of responsibility will request the sender and request decoupled.

When to use: when dealing with many channel messages to filter.

Key Code: Handler polymerization inside its own judgment is appropriate in HandlerRequest, if conditions did not reach down the pass, set to go before whom passed.

Application examples:  1, The Dream of Red Mansions "Drumming pass to spend." 2, JS events bubbling. 3, JAVA WEB Encoding processing in the Apache Tomcat, Struts2 interceptor, jsp servlet's Filter.

Advantages:  1, decouple. It requests the sender and receiver decoupling. 2, the object is simplified. Such that the object does not need to know the structure of the chain. 3, enhance the flexibility of assigning responsibilities to objects. By changing the members of the chain or the mobilization of their order, allows to dynamically add or delete liability. 4, adding new class request processing easy.

Disadvantages:  1, does not necessarily guarantee the request is received. 2, system performance will be affected, but not very convenient when performing debugging code may cause the cycle call. 3, may not be readily observable characteristic runtime hinder debugging.

Be used:  1, a plurality of the same object can process a request, the request is processed concrete which object is determined automatically by the run time. 2, in a case where the recipient is not explicitly specified, submit a request to a plurality of objects. 3, a set of objects may be dynamically assigned to process the request.

 

Guess you like

Origin www.cnblogs.com/qlqwjy/p/11386908.html