java Design Patterns--Responsibility Chain Patterns

Keywords: PHP

Chain of Responsibility Model

Responsibility chain pattern is an object behavior pattern, which enables multiple objects to process requests, thus avoiding the coupling between the sender and the receiver of requests, linking these objects into a chain, and passing the request along the chain step by step until one object processes it.

In our life, we will encounter many scenarios about the responsibility chain model. For example, A is sick at work and needs leave. If only three days is needed, it only needs the group leader's consent to deal with it. If one week is needed, it may need the Department Manager to deal with it. If one month is needed, it needs the general manager to come to work. Li. This process is basically based on different permissions to gradually report the processing of the leave request, which can be seen as a responsibility chain model scenario.

 

Responsibility Chain Model Structural Diagram

 

As can be seen from the figure, the responsibility chain pattern consists of two types of roles:

Handler: The Abstract handler role defines the interface for processing requests, as well as a successor chain role.

ConcreteHandler: The specific handler role handles requests that he can handle, and also accesses its successors. If the object cannot process the request, it passes the request to its successors.

Applicability of Responsibility Chain Model

  • The responsibility chain pattern applies to multiple objects that can process a request, and which object can process the request at runtime.

  • The client wants to submit a request to one of multiple objects without specifying the specific recipient.

  • A collection of objects that can handle a request can be dynamically specified

Example of Chain of Responsibility Patterns

An example of the chain of responsibility is used to illustrate the basic use of the chain of responsibility model in the scenario described at the beginning of this article.

First, define an abstract processing class

 

public abstract class Handler {
    protected Handler handler;

    public Handler(Handler handler) {
        this.handler = handler;
    }

    public abstract void handlerForLeave(String name,int days);
}

 

Secondly, the logic of group leader, department leader and general manager to deal with leave is defined respectively.

First, the team leader

public class LeaderHandler  extends Handler{

    public LeaderHandler(Handler handler) {
        super(handler);
    }

    @Override
    public void handlerForLeave(String name,int days) {
        if (name.equals("Zhang San")){
            if (days<=3){
                System.out.println("Agree!"+name+"Application for leave and approval of leave"+days+"day");
            }else {
                System.out.println("leader If the application cannot be processed, the application shall be transmitted to the superior.");
                handler.handlerForLeave(name,days);
            }
        }else {
            /*Other processing logic*/
        }
    }
}

Next comes the Department manager:

public class DeptManagerHandler extends Handler {

    public DeptManagerHandler(Handler handler) {
        super(handler);
    }

    @Override
    public void handlerForLeave(String name, int days) {
        if (name.equals("Zhang San")){
            if (days<=7){
                System.out.println("Agree!"+name+"Application for leave and approval of leave"+days+"day");
            }else {
                System.out.println("DeptManager If the application cannot be processed, the application shall be transmitted to the superior.");
                handler.handlerForLeave(name,days);
            }
        }else {
            /*Other processing logic*/
        }
    }
}

Finally, the general manager

public class GeneralManagerHandler extends Handler {

    public GeneralManagerHandler(Handler handler) {
        super(handler);
    }

    @Override
    public void handlerForLeave(String name, int days) {
        if (name.equals("Zhang San")){
            if (days<=30){
                System.out.println("Agree!"+name+"Application for leave and approval of leave"+days+"day");
            }else {
                System.out.println("Disagree");
            }
        }else {
            /*Other processing logic*/
        }
    }
}

Then through the client call to leave for 10 days as an example.

public class Client {
    public static void main(String[] args) {
        GeneralManagerHandler generalManagerHandler = new GeneralManagerHandler(null);
        DeptManagerHandler deptManagerHandler = new DeptManagerHandler(generalManagerHandler);
        LeaderHandler leaderHandler = new LeaderHandler(deptManagerHandler);

        leaderHandler.handlerForLeave("Zhang San", 10);
    }
}


/*
Operation results:
        eader If the application cannot be processed, the application shall be transmitted to the superior.
        DeptManager If the application cannot be processed, the application shall be transmitted to the superior.
        Agree to Zhang San's application for leave and grant 10 days'leave*/

From the above examples, we can see how the responsibility chain pattern can be used basically, but there is a minor problem in the above examples, that is, the invocation and sequence of the whole leave process are all determined when the client calls, and the information of the first processor is also determined, so that if the new processor is Not to change the client code, or to modify the first processor also need to modify the client code, so is it not friendly to the client or not?

Here is an upgraded version of this example, which can completely decouple the client from the specific processing logic. The logic of this example is based on the responsibility chain pattern logic in Filter in Servlet.

There are some minor changes to the Handler class and the LeaderHandler, DeptManagerHandler, and General ManagerHandler classes as follows

public interface Handler {
    public abstract void handlerForLeave(String name,int days, HandlerChain handlerChain);
}
public class LeaderHandler implements Handler {
    @Override
    public void handlerForLeave(String name, int days, HandlerChain handlerChain) {
        if (name.equals("Zhang San")) {
            if (days <= 3) {
                System.out.println("Agree!" + name + "Application for leave and approval of leave" + days + "day");
                return;
            } else {
                System.out.println("leader If the application cannot be processed, the application shall be transmitted to the superior.");
                handlerChain.handlerForLeave(name, days, handlerChain);
            }
        } else {
            /*Other processing logic*/
        }
    }
}
public class DeptManagerHandler implements Handler {
    @Override
    public void handlerForLeave(String name, int days, HandlerChain handlerChain) {
        if (name.equals("Zhang San")) {
            if (days <= 7) {
                System.out.println("Agree!" + name + "Application for leave and approval of leave" + days + "day");
                return;
            } else {
                System.out.println(" DeptManager If the application cannot be processed, the application shall be transmitted to the superior.");
                handlerChain.handlerForLeave(name, days, handlerChain);
            }
        } else {
            /*Other processing logic*/
        }
    }
}
public class GeneralManagerHandler implements Handler {
    @Override
    public void handlerForLeave(String name, int days, HandlerChain handlerChain) {
        if (name.equals("Zhang San")){
            if (days<=30){
                System.out.println("Agree!"+name+"Application for leave and approval of leave"+days+"day");

            }else {
                System.out.println("Disagree");
            }
        }else {
            /*Other processing logic*/
        }
        return;
    }
}

On this basis, a HandlerChain class is added to preserve the order of the specific request processing class and the request processing class, and the handlerForLeave method of the HandlerChain class is used as the beginning of a general request processing method, so that the logical order of the request processing is not changed when the client calls. Other changes, in this example, the handlerList in the HandlerChain class is initialized on the client side. In the actual invocation, the process of client initialization can be put into the configuration file so that the modification of any link in the responsibility chain only needs to modify the configuration file.

public class HandlerChain implements Handler {
    private int sizeCount = 0;
    private List<Handler> handlerList;

    public void addHandler(Handler handler) {
        if (handlerList == null) {
            handlerList = new ArrayList<Handler>();
        }
        handlerList.add(handler);
    }

    @Override
    public void handlerForLeave(String name, int days,HandlerChain handlerChain) {
        if (sizeCount == handlerList.size()) {
            return;
        }
        handlerList.get(sizeCount++).handlerForLeave(name, days,handlerChain);
    }
}

Client calls are as follows:

public class Client {
    public static void main(String[] args) {
        GeneralManagerHandler generalManagerHandler = new GeneralManagerHandler();
        DeptManagerHandler deptManagerHandler = new DeptManagerHandler();
        LeaderHandler leaderHandler = new LeaderHandler();

        HandlerChain handlerChain = new HandlerChain();
        handlerChain.addHandler(leaderHandler);
        handlerChain.addHandler(deptManagerHandler);
        handlerChain.addHandler(generalManagerHandler);
        handlerChain.handlerForLeave("Zhang San", 10, handlerChain);
    }
}
/*Operation results:
        leader If the application cannot be processed, the application shall be transmitted to the superior.
        DeptManager If the application cannot be processed, the application shall be transmitted to the superior.
        Agree to Zhang San's application for leave and grant 10 days'leave*/

Advantages of the Responsibility Chain Model

Firstly, the responsibility chain model achieves the loose coupling between the requester and the handler of the request. The change of their business logic will not affect the other party. Secondly, adding, deleting and modifying any link in the responsibility chain will not affect the whole process of the responsibility chain. Finally, any link in the responsibility chain has independent responsibilities. The request Office The logic of reason is also independent and independent of each other.

Posted by jwadenpfuhl on Tue, 30 Jul 2019 15:31:32 -0700