Java 设计模式-责任链模式

130 阅读2分钟
  1. 需求分析:
    一个公司的审批流程是层层递进的. 假设现在你有一个请假的请求, 请假两天及以内经理同意就可以了, 请假五天及以内需要总监同意, 请假大于五天需要总经理同意.

    /**
     * 请求
     */
    public class Request {
        public static final String REQUEST_TYPE_DAY_OFF = "day_off";
        private String requestType;
        private String int number;
        
        public void setRequestType(String requestType) {
            this.requestType = requestType;
        }
        
        public String getRequestType() {
            return this.requestType;
        }
        
        public void setNumber(int number) {
            this.number = number;
        }
        
        public int getNumber() {
            return this.number;
        }
    }
    
    /**
     * 管理者
     */
    public class Manager {
        private String name;
        
        public Manager(String name) {
            this.name = name;
        }
        
        public void getResult(String managerLevel, Request request) {
            if (managerLevel == "经理") {
                if (request.getRequestType() == Request.REQUEST_TYPE_DAY_OFF && request.getNumber() <= 2) {
                    System.out.println(String.format("%s同意请假, 请假天数为%d", this.name, request.getNumber()));
                } else {
                    System.out.println(String.format("请假天数大于两天, %s无权处理", this.name));
                }
            } else if (managerLevel == "总监") {
                if (request.getType() ==  Request.REQUEST_TYPE_DAY_OFF && request.getNumber() <= 5) {
                    System.out.println(String.format("%s同意请假, 请假天数为%d", this.name, request.getNumber()));
                } else {
                    System.out.println(String.format("请假天数大于两天, %s无权处理", this.name));
                }
            } else if (managerLevel == "总经理") {
                if (request.getRequestType() ==  Request.REQUEST_TYPE_DAY_OFF) {
                     System.out.println(String.format("%s同意请假, 请假天数为%d", this.name, request.getNumber()));
                }
            }
        }
    }
    
    public class Client {
        public static void main(String[] args) {
            Manager commonManager = new Manager("王经理");
            Manager majordomo = new Manager("李总监");
            Manager generalManager = new Manager("周总经理");
            Request request = new Request(Request.REQUEST_TYPE_DAY_OFF);
            commonManager.getResult(request);
            majordomo.getResult(request);
            generalManager.getResult(request);
        }
    }
    

    现在存在的问题是所有处理的判断都是在Manager#getResult()方法里面进行的. 如果需要增加审批中间人, 就需要对Manager#getResult()方法进行改动. 采用职责链对审批处理进行改动, 让审批流程形成一条审批链.

    /**
     * 抽象的管理者类
     */
    public abstract class Manager {
        protected String name;
        protected Manager superior;
        
        public Manager(String name) {
            this.name = name;
        }
        
        public void setSuperior(Manager superior) {
            this.superior = superior;
        }
        
        public abstract void handleRequest(Request request);
    }
    
    /**
     * 经理
     */
    public class CommonManager extends Manager {
        public CommonManager(String name) {
            super(name);
        }
        
        @Override
        public void handleRequest(Request request) {
            if (request.getRequestType() == Request.REQUEST_TYPE_DAY_OFF && request.getNumber() <= 2) {
                System.out.println(String.format("%s同意请假, 请假天数为%d", this.name, request.getNumber()));
            } else {
                if (superior != null) {
                    superior.handleRequest(request);
                }
            }
        }
    }
    
    /**
     * 总监
     */
    public class Majordomo extends Manager {
        
        public Majordomo(String name) {
            super(name);
        }
        
        @Override
        public void handleRequest(Request request) {
            if (request.getRequestType() == Request.REQUEST_TYPE_DAY_OFF && request.getNumber() <= 5) {
                System.out.println(String.format("%s同意请假, 请假天数为%d", this.name, request.getNumber()));
            } else {
                if (superior != null) {
                    superior.handleRequest(request);
                }
            }
        }
    }
    
    /**
     * 总经理
     */
    public class GeneralManager extends Manager {
        
        public GeneralManager(String name) {
            super(name);
        }
        
        @Override
        public void handleRequest(Request request) {
            if (request.getRequestType() == Request.REQUEST_TYPE_DAY_OFF) {
                System.out.println(String.format("%s同意请假, 请假天数为%d", this.name, request.getNumber()));
            }
        }
    }
    
    public class Client {
        public static void main(String[] args) {
            Manager commonManager = new Manager("王经理");
            Manager majordomo = new Manager("李总监");
            Manager generalManager = new Manager("周总经理");
            // 这里上级是可以动态设置的, 可以根据需求调整
            commonManager.setSuperior(majordomo);
            majordomo.setSuperior(generalManager);
            Request request = new Request(Request.REQUEST_TYPE_DAY_OFF);
            // 这里只需要调用一次方法, 整个需要就会沿着责任连进行传递
            commonManager.handleRequest(request);
        }
    }
    
  2. 责任连模式的定义:
    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 objects and pass the request along the chain util an object handle it(使多个对象都有机会处理请求, 从而避免了请求的发送者和接受者之间的耦合关 系. 将这些对象连成一条链, 并沿着这条链传递该请求, 直到有对象处理它为止).

    Chain of Responsibility

  3. 责任连模式的应用: javax.servlet.Filter#doFilter() 方法

  4. 参考:
    [1] : Java 库中的设计模式
    [2] : 设计模式之禅
    [3] : Head First 设计模式
    [4] : 大话设计模式