• 尚硅谷设计模式笔记-职责链模式


    Table of Contents generated with DocToc

    笔记来源:尚硅谷设计模式

    一、需求

    学校OA系统的采购审批项目:需求是

    1. 采购员采购教学器材
    2. 如果金额小于等于5000,由教学主任审批
    3. 如果金额小于等于10000,由院长审批
    4. 如果金额小于等于30000,由副校长审批
    5. 如果金额超过30000以上,有校长审批

    二、传统的设计方案

    传统方式是:接收到一个采购请求后,根据采购金额【if-else】来调用对应的Approver (审批人)完成审批。

    问题:

    • 当审批金额发生了变化。那么则要更改if-else的代码,如果条件很复杂,修改起来很困难
    • 客户端必须明确的知道有多少个审批级别,并且对应的金额

    Client和aprrover有强耦合关系


    三、职责链模式

    职责链模式(Chain of Responsibility Pattern),又叫责任链模式,为请求创建了一个接收者对象的链(简单示意图)。 这种模式对请求的发送者和接收者进行解耦。

    我们将处理请求发送给教务主任,如果可以处理就处理,如果不能处理就交给下一个角色(院长),如果院长可以处理就处理,如果不能处理就交给下一个角色(副校长),直到校长。

    首先先写好请求类:

    public class PurchaseRequest {
        private double price=0.0f;//金额
        private int id;
    
        public PurchaseRequest(double price, int id) {
            this.price = price;
            this.id = id;
        }
    
    /*get set省略*/
    }
    

    然后创建虚拟的解决类(相当于处理者):

    public abstract class Handler {
        Handler successor;//保存下一个处理者
        String name;
    
        public Handler(String name) {
            this.name = name;
        }
        //处理审批请求的方法,得到一个请求,处理是子类完成,因此该方法做成抽象
        public abstract void processRequest(PurchaseRequest request) throws Exception;
    
        public void setSuccessor(Handler successor) {
            this.successor = successor;
        }
    }
    

    然后用子类继承,并实现处理方法(此处以系主任为例):

    //系主任
    public class DepartmentApprover extends Handler{
        public DepartmentApprover(String name) {
            super(name);
        }
    
        @Override
        public void processRequest(PurchaseRequest request) throws Exception {
            if(request.getPrice() <= 5000)
                System.out.println("请求编号为"+request.getId()+"被"+this.name+"处理");
            
            //如果不满足条件,则丢给下一个处理者
            else
                successor.processRequest(request);
    
        }
    }
    

    在Client中生成责任链,并发送请求【切记责任链要设计成环状,万一有个1000元的需求从中间责任人(比如副校长)开始处理,也能够传递到系主任】

    public class Client {
        public static void main(String[] args) throws Exception {
            PurchaseRequest request = new PurchaseRequest(3500,1);
            Handler departmentApprover = new DepartmentApprover("系主任");
            Handler collegeApprover = new CollegeApprover("院长");
            Handler viceSchoolApprover = new ViceSchoolApprover("副校长");
            Handler schoolApprover = new SchoolApprover("校长");
    
            //设置责任链(处理人构成环状)
            schoolApprover.setSuccessor(departmentApprover);
            viceSchoolApprover.setSuccessor(schoolApprover);
            collegeApprover.setSuccessor(viceSchoolApprover);
            departmentApprover.setSuccessor(collegeApprover);
    
    
            departmentApprover.processRequest(request);
        }
    }
    

    输出为:

    请求编号为1被系主任处理

    整个实例类图为:

  • 相关阅读:
    C#中AppDomain.CurrentDomain.BaseDirectory及各种路径获取方法
    Sqlserver查询数据库文件大小和剩余空间
    【免费视频】使用VS Code开发ASP.NET Core WebAPI应用程序
    WinForm自动记录从上次关闭位置启动窗体
    c#通过socket判断服务器连接是否正常
    ASP.NET Core Windows服务开发技术实战演练
    win7/win10 设置始终以管理员身份运行cmd窗口
    投资回报率,止损率
    等额本息,等额本金,先息后本解读
    银行加息有什么影响(央行加息,对股市和房价有何影响?)
  • 原文地址:https://www.cnblogs.com/theory/p/13338726.html
Copyright © 2020-2023  润新知