Design Patterns_Behavioral Patterns - "Chain of Responsibility Patterns"

Design Patterns_Behavioral Patterns - "Chain of Responsibility Patterns"

The notes are organized from the detailed explanation of Java design patterns by dark horse programmers, 23 Java design patterns (diagram + framework source code analysis + actual combat)

overview

In real life, there are often such cases: a request can be processed by multiple objects, but the processing conditions or permissions of each object are different. For example, if a company employee asks for leave, the leaders who can approve the leave include the department head, deputy general manager, general manager, etc., but the number of days that each leader can approve is different. Employees must find different leaders to sign according to the number of days they want to ask for leave. That is to say, employees must remember information such as the name, phone number and address of each leader, which increases the difficulty. There are many other examples like this, such as seeking reimbursement for business trips from leaders, and the game of "drumming and passing flowers" in daily life.

definition

  • Responsibility chain mode, also known as responsibility chain mode, in order to avoid coupling the request sender with multiple request processors, all request processors are connected into a chain by remembering the reference of the next object through the previous object; when When a request occurs, the request can be passed along this chain until an object handles it.

image-20230109124843959

structure

The Chain of Responsibility Pattern mainly includes the following roles:

  • Abstract handler (Handler) role: defines an interface for processing requests, including abstract processing methods and a subsequent connection (a reference to the next object).
  • Concrete Handler (Concrete Handler) role: implement the processing method of the abstract handler, judge whether the request can be processed, if it can handle the request, process it, otherwise transfer the request to its successor.
  • Client class (Client) role: Create a processing chain and submit a request to the specific processor object at the head of the chain. It does not care about the processing details and the delivery process of the request.

Case realization

Now it is necessary to develop a leave process control system. Leave of less than 1 day only needs the approval of the team leader; leave of 1 to 3 days requires the approval of the department manager; leave of 3 to 7 days requires the approval of the general manager.

The class diagram is as follows:

code show as below:

  • written request for leave

    public class LeaveRequest {
          
          
        
        private String name; // 姓名
        private int num; // 请假天数
        private String content; // 请假内容
    
        public LeaveRequest(String name, int num, String content) {
          
          
            this.name = name;
            this.num = num;
            this.content = content;
        }
    
        public String getName() {
          
          
            return name;
        }
    
        public int getNum() {
          
          
            return num;
        }
    
        public String getContent() {
          
          
            return content;
        }
    }
    
  • abstract handler role

    public abstract class Handler {
          
          
        
        protected final static int NUM_ONE = 1;
        protected final static int NUM_THREE = 3;
        protected final static int NUM_SEVEN = 7;
    
        // 该领导处理的请假天数区间
        private int numStart;
        private int numEnd;
    
        // 领导上面还有领导(后继连接,下一个对象的引用)
        private Handler nextHandler;
    
        // 设置请假天数范围 上不封顶
        public Handler(int numStart) {
          
          
            this.numStart = numStart;
        }
    
        // 设置请假天数范围
        public Handler(int numStart, int numEnd) {
          
          
            this.numStart = numStart;
            this.numEnd = numEnd;
        }
    
        // 设置上级领导
        public void setNextHandler(Handler nextHandler){
          
          
            this.nextHandler = nextHandler;
        }
    
        // 提交请假条
        public final void submit(LeaveRequest leave){
          
          
            if (0 == this.numStart) {
          
          
                return;
            }
    
            // 如果请假天数达到该领导者的处理要求
            if (leave.getNum() >= this.numStart) {
          
          
                this.handleLeave(leave);
    
                // 如果还有上级 并且请假天数超过了当前领导的处理范围
                if (this.nextHandler != null && leave.getNum() > numEnd) {
          
          
                    this.nextHandler.submit(leave); // 继续往上提交 责任链模式
                } else {
          
          
                    System.out.println("流程结束");
                }
            }
        }
    
        // 各级领导处理请假条方法
        protected abstract void handleLeave(LeaveRequest leave);
    }
    
  • Concrete Processor Role

    // 具体处理者-小组长
    public class GroupLeader extends Handler {
          
          
        public GroupLeader() {
          
          
            // 小组长处理1天以下的请假
            super(0, Handler.NUM_ONE);
        }
    
        @Override
        protected void handleLeave(LeaveRequest leave) {
          
          
            System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "。");
            System.out.println("小组长审批:同意。");
        }
    }
    
    // 具体处理者-部门经理
    public class Manager extends Handler {
          
          
        public Manager() {
          
          
            // 部门经理处理1-3天的请假
            super(Handler.NUM_ONE, Handler.NUM_THREE);
        }
    
        @Override
        protected void handleLeave(LeaveRequest leave) {
          
          
            System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "。");
            System.out.println("部门经理审批:同意。");
        }
    }
    
    // 具体处理者-总经理
    public class GeneralManager extends Handler {
          
          
        public GeneralManager() {
          
          
            // 部门经理处理3-7天的请假
            super(Handler.NUM_THREE, Handler.NUM_SEVEN);
        }
    
        @Override
        protected void handleLeave(LeaveRequest leave) {
          
          
            System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "。");
            System.out.println("总经理审批:同意。");
        }
    }
    
  • test class

    public class Client {
          
          
        public static void main(String[] args) {
          
          
            // 请假条来一张
            LeaveRequest leave = new LeaveRequest("张三", 5, "身体不适");
    
            // 各位领导
            GroupLeader groupLeader = new GroupLeader();
            Manager manager = new Manager();
            GeneralManager generalManager = new GeneralManager();
    
            groupLeader.setNextHandler(manager); // 小组长的领导是部门经理
            manager.setNextHandler(generalManager); // 部门经理的领导是总经理
            // 此时责任链已经设置成功了
            // 之所以在这里设置上级领导,是因为可以根据实际需求来更改设置,如果实战中上级领导人都是固定的,则可以移到领导实现类中。
    
            // 提交申请
            groupLeader.submit(leave);
        }
    }
    

    output

    张三请假5天,身体不适。
    小组长审批:同意
    张三请假5天,身体不适。
    部门经理审批:同意
    张三请假5天,身体不适。
    总经理审批:同意
    流程结束!
    

Advantages and disadvantages

advantage

  • Reduced coupling between objects
    • This pattern reduces the coupling between request sender and receiver.
  • Enhanced system scalability
    • New request processing classes can be added as needed to meet the principle of opening and closing.
  • Enhanced flexibility in assigning responsibilities to objects
    • When the workflow changes, you can dynamically change the members in the chain or modify their order, and you can also dynamically add or delete responsibilities.
  • Chain of Responsibility simplifies the connection between objects
    • An object only needs to keep a reference pointing to its successor, and does not need to keep references to all other handlers, which avoids the use of numerous if or if···else statements.
  • responsibility sharing
    • Each class only needs to handle the work that it should handle, and pass the unhandled ones to the next object to complete, clarify the scope of responsibility of each class, and conform to the single responsibility principle of the class.

shortcoming

  • There is no guarantee that every request will be processed. Since a request has no clear recipient, there is no guarantee that it will be processed, and the request may go all the way down the chain without being processed.
  • Compared with a long chain of responsibility, the processing of the request may involve multiple processing objects, and the system performance will be affected to a certain extent.
  • The rationality of the establishment of the chain of responsibility depends on the guarantee of the client, which increases the complexity of the client, and may cause system errors due to incorrect settings of the chain of responsibility, such as circular calls.

Source Code Analysis-JavaWeb

In JavaWeb application development, FilterChain is a typical application of the chain of responsibility (filter) pattern. The following is the simulation implementation analysis of Filter:

  • Simulate web request Request and web response Response

    public interface Request {
          
          
     
    }
    
    public interface Response {
          
          
     
    }
    
  • Analog web filter Filter

    public interface Filter {
          
          
    	public void doFilter(Request req, Response res, FilterChain c);
    }
    
  • Simulate implementation of concrete filters

    public class FirstFilter implements Filter {
          
          
        @Override
        public void doFilter(Request request, Response response, FilterChain chain) {
          
          
    
            System.out.println("过滤器1 前置处理");
    
            // 先执行所有request再倒序执行所有response
            chain.doFilter(request, response);
    
            System.out.println("过滤器1 后置处理");
        }
    }
    
    public class SecondFilter implements Filter {
          
          
        @Override
        public void doFilter(Request request, Response response, FilterChain chain) {
          
          
    
            System.out.println("过滤器2 前置处理");
    
            // 先执行所有request再倒序执行所有response
            chain.doFilter(request, response);
    
            System.out.println("过滤器2 后置处理");
        }
    }
    
  • Simulate the implementation of the filter chain FilterChain

    public class FilterChain {
          
          
    
        private List<Filter> filters = new ArrayList<Filter>();
    
        private int index = 0;
    
        // 创建过滤器链对象 -> 链式调用
        public FilterChain addFilter(Filter filter) {
          
          
            this.filters.add(filter);
            return this;
        }
    
        public void doFilter(Request request, Response response) {
          
          
            if (index == filters.size()) {
          
          
                return;
            }
            Filter filter = filters.get(index);
            index++;
            filter.doFilter(request, response, this);
        }
    }
    
  • test class

    public class Client {
          
          
        public static void main(String[] args) {
          
          
            Request  req = null;
            Response res = null;
    
            FilterChain filterChain = new FilterChain();
            filterChain.addFilter(new FirstFilter()).addFilter(new SecondFilter());
            filterChain.doFilter(req, res);
        }
    }
    

    output

    过滤器1 前置处理
    过滤器2 前置处理
    过滤器2 后置处理
    过滤器1 后置处理
    

Guess you like

Origin blog.csdn.net/weixin_53407527/article/details/128628042