Application scenarios

HTTP Web request processing, after the request will be transcoding, parsing, parameter encapsulation, authentication and a series of processing (responsibility), and after how much processing can be flexibly adjusted so how to do it? How about putting all of your processing in one class? Divided into multiple classes and how to flexibly combine together?

A simple example

Request:

public interface Request {
    //do something...
}
Copy the code

ResponsibilityChain class:

public class ResponsibilityChain {

    private List<Responsibility> responsibilityList = new ArrayList<>();

    private Integer index = 0;
    
    public void process(Request request) {
        if (this.index < responsibilityList.size()) {
            this.responsibilityList.get(index++).process(request, this); }}/** joins the chain */
    public void register(Responsibility responsibility) {
        this.responsibilityList.add(responsibility); }}Copy the code

Responsibility interface:

public interface Responsibility {
    void process(Request request, ResponsibilityChain chain);
}
Copy the code

Responsibility implementation class:

public class ResponsibilityA implements Responsibility {
    @Override
    public void process(Request request, ResponsibilityChain chain) {
        System.out.println("Transcoding"); chain.process(request); }}Copy the code
public class ResponsibilityB implements Responsibility {
    @Override
    public void process(Request request, ResponsibilityChain chain) {
        System.out.println("Resolution"); chain.process(request); }}Copy the code
public class ResponsibilityC implements Responsibility {
    @Override
    public void process(Request request, ResponsibilityChain chain) {
        System.out.println("Parameter encapsulation"); chain.process(request); }}Copy the code
public class ResponsibilityD implements Responsibility {
    @Override
    public void process(Request request, ResponsibilityChain chain) {
        System.out.println("Authentication"); chain.process(request); }}Copy the code

The test class:

public class Test {
    public static void main(String[] args) {
        ResponsibilityChain chain = new ResponsibilityChain();
        chain.register(new ResponsibilityA());
        chain.register(new ResponsibilityB());
        chain.register(new ResponsibilityC());
        chain.register(new ResponsibilityD());
        chain.process(newRequest() { }); }}Copy the code

Class diagram:

Chain of Responsibility model

define

All the handlers, they join the chain, and when one is done, it passes to the next or each recipient contains a reference to the other recipient, and if an object can’t handle the request, it passes the same request to the next recipient

  1. Abstract out the responsibility interface, the concrete responsibility logic to realize the interface
  2. Concrete implementations are grouped into chains as required by the process
  3. User use chain

Typical examples are Filter and Interceptor

intentions

Avoid coupling the request sender with the receiver, make it possible for multiple objects to receive the request, connect the objects into a chain, and pass the request along the chain until an object handles it

Main problem solving

The handler on the responsibility chain is responsible for processing the request, and the client only needs to send the request to the responsibility chain. There is no need for the details of relationship processing and the delivery of the request. The sender and handler of the request are decoupled

When to use

  1. The system already has a chain of handler objects, which may be given by the composition pattern
  2. More than one handler object will process a request, and it is not clear in advance which handler object will process a request. Handler objects are dynamically determined
  3. The system wants to make a request to one of several handler objects, but it is not obvious which handler object will handle the request
  4. The collection of handler objects that process a request needs to be specified dynamically

The advantages and disadvantages

Advantages:

  1. Sender and receiver decoupled, low coupling
  2. Simplifies the object. The object does not need to know the structure of the chain
  3. Responsibilities can be dynamically added or removed by changing members in the chain or reordering them
  4. It is convenient to add new request handling classes

Disadvantages:

  1. There is no guarantee that the request will be received
  2. System performance will suffer, and it will be inconvenient to debug the code, which may cause circular calls
  3. Runtime characteristics may not be easily observed, hindering debugging

The class diagram is as follows:Roles involved:

  1. The Handler role: Defines an interface to handle requests. If necessary, the interface can define a method to set and return references to the next parent. This role is usually implemented by an abstract class or interface
  2. The ConcreteHandler role: When a ConcreteHandler receives a request, it can either process it or pass it to the next; The concrete handler holds a reference to the next one, so the concrete handler can access the next one if needed

Code example: Handler class:

public abstract class Handler {

    protected Handler successor;

    /** Call this method to process the request */
    public abstract void handlerRequest(a);

    /** Method */
    public Handler getSuccessor(a) {
        return successor;
    }

    /** Call this method to set the next */
    public void setSuccessor(Handler successor) {
        this.successor = successor; }}Copy the code

ConcreteHandler:

public class ConcreteHandler1 extends Handler {
    @Override
    public void handlerRequest(a) {
        if(getSuccessor() ! =null) {
            System.out.println("Request passed on to the next:" + getSuccessor().getClass().getName());
            getSuccessor().handlerRequest();
        } else {
            System.out.println("Request processed in ConcreteHandler1"); }}}Copy the code
public class ConcreteHandler2 extends Handler {
    @Override
    public void handlerRequest(a) {
        if(getSuccessor() ! =null) {
            System.out.println("Request passed on to the next:" + getSuccessor());
            getSuccessor().handlerRequest();
        } else {
            System.out.println("Request processed in ConcreteHandler2"); }}}Copy the code

Client:

public class Client {

    static private Handler handler1;

    static private Handler handler2;

    public static void main(String[] args) {
        handler1 = new ConcreteHandler1();
        handler2 = newConcreteHandler2(); handler1.setSuccessor(handler2); handler1.handlerRequest(); }}Copy the code

Class diagram:

Beat the drum to pass the story of flowers

Drum passing flowers is a lively and intense drinking game. In the banquet, the guests sit down in turn and one person beats the drum. When the drum starts to beat, the bouquet of flowers will be passed in turn. Here is a small example of the story of beating drums and spreading flowers in a Dream of Red Mansions:Abstract interface Player class:

public abstract class Player {

    private Player player;

    /** The request to execute the liquor order */
    abstract public  void handlerRequest(int index);

    /** Sets the next bearer */
    public void setPlayer(Player player) {
        this.player = player;
    }

    /** passes the flower to the next family, if not, end */
    public void next(int index) {
        if(player ! =null) {
            player.handlerRequest(index);
        } else {
            System.out.println("The passing of flowers is over."); }}}Copy the code

People who participate in drumming and passing flowers:

public class JiaMu extends Player {

    public JiaMu(Player player) {
        this.setPlayer(player);
    }

    @Override
    public void handlerRequest(int index) {
        if (index == 1) {
            System.out.println("Mama Jammu carries out the drinking order.");
        } else {
            System.out.println("Jammy passes the flower to the next."); next(index); }}}Copy the code
public class JiaShe extends Player {

    public JiaShe(Player player) {
        this.setPlayer(player);
    }

    @Override
    public void handlerRequest(int index) {
        if (index == 2) {
            System.out.println("Jia She carries out the drinking order.");
        } else {
            System.out.println("Jasmine passes flowers to the next."); next(index); }}}Copy the code
public class JiaZheng extends Player {

    public JiaZheng(Player player) {
        this.setPlayer(player);
    }

    @Override
    public void handlerRequest(int index) {
        if (index == 3) {
            System.out.println("Jia Zheng executes the drinking order.");
        } else {
            System.out.println("Jia Zheng passes the flower to the next."); next(index); }}}Copy the code
public class JiaBaoYu extends Player {

    public JiaBaoYu(Player player) {
        this.setPlayer(player);
    }

    @Override
    public void handlerRequest(int index) {
        if (index == 4) {
            System.out.println("Jia Baoyu carries out the drinking order.");
        } else {
            System.out.println("Jia Baoyu passes flowers to the next."); next(index); }}}Copy the code
public class JiaHuan extends Player {

    public JiaHuan(Player player) {
        this.setPlayer(player);
    }

    @Override
    public void handlerRequest(int index) {
        if (index == 5) {
            System.out.println("Jia Huan executes the drinking order.");
        } else {
            System.out.println("Jia Huan passes the flower to the next."); next(index); }}}Copy the code

The drums:

public class DrinkingGame {

    static private Player player;

    public static void main(String[] args) {
        player = new JiaMu(
                  new JiaShe(
                  new JiaZheng(
                  new JiaBaoYu(
                  new JiaHuan(null)))));
        // Set the fourth execution order
        player.handlerRequest(4); }}Copy the code

Class diagram: