【设计模式】职责链模式

职责链模式详解与应用

系列文章目录



在这里插入图片描述

在本篇文章,我们以申请加薪、请假这一事件为例,

加薪代码初步

无论是申请加薪还是请假,都是一种申请,申请就要有申请类别、申请内容、申请数量。

class Request{
        //申请类别
        private String requestType;
        public String getRequestType(){
            return this.requestType;
        }
        public void setRequestType(String value){
            this.requestType = value;
        }

        //申请内容
        private String requestContent;
        public String getRequestContent(){
            return this.requestContent;
        }
        public void setRequestContent(String value){
            this.requestContent = value;
        }
        //数量
        private int number;
        public int getNumber(){
            return this.number;
        }
        public void setNumber(int value){
            this.number = value;
        }
    }
    class Manager{
        protected String name;
        public Manager(String name){
            this.name = name;
        }
        public void getResult(String manageLevel,Request request){
            if(manageLevel == "经理"){
                if(request.getRequestType() == "请假" && request.getNumber() <= 2){
                    System.out.println(this.name + ": " + request.getRequestContent() + "数量 : "+ request.getNumber() + "天,被批准");
                }else{
                    System.out.println(this.name + ":" + request.getRequestContent() + "数量 :" + request.getNumber() + "天,无权处理");
                }
            }else if(manageLevel == "总监"){
                if(request.getRequestType() == "请假" && request.getNumber() <= 5){
                    System.out.println(this.name + ": " + request.getRequestContent() + "数量 : "+ request.getNumber() + "天,被批准");
                }else{
                    System.out.println(this.name + ":" + request.getRequestContent() + "数量 :" + request.getNumber() + "天,无权处理");
                }
            }else if(manageLevel == "总经理"){
                if(request.getRequestType() == "请假" && request.getNumber() <= 5) {
                    System.out.println(this.name + ": " + request.getRequestContent() + "数量 : " + request.getNumber() + "天,被批准");
                }else if(request.getRequestType() == "加薪" && request.getNumber() <= 5000){
                    System.out.println(this.name + ": " + request.getRequestContent() + "数量: " + request.getNumber() + "元,被批准");
                }else if(request.getRequestType() == "加薪" && request.getNumber() > 5000){
                    System.out.println(this.name + ": " + request.getRequestContent() + "数量: " + request.getNumber() + "元,再说吧");
                }
            }
        }
    }
    //客户端代码
    public static void main(String[] args) {
        //三个不同级别的管理者
        Manager manager = new Manager("老大");
        Manager director = new Manager("老二");
        Manager generalManager = new Manager("老三");
        //小张请求加薪10000元
        Request request = new Request();
        request.setRequestContent("加薪");
        request.setRequestContent("小张请求加薪");
        request.setNumber(10000);
        //不同级别对加薪请求做判断和处理
        manager.getResult("经理",request);
        director.getResult("总监",request);
        generalManager.getResult("总经理",request);
        //小张请假三天
        Request request2 = new Request();
        request2.setRequestType("请假");
        request2.setRequestContent("小张请假");
        request2.setNumber(3);
        //不同级别对请假需求做判断
        manager.getResult("经理",request2);
        director.getResult("总监",request2);
        generalManager.getResult("总经理",request2);
    }

这样的代码看着确实不够美观,在管理者类中结果的方法太长。有很多的分支判断,这是非常不好的设计。而且在增加其他的管理类别,比如项目经理、部门经理、人力总监等,那就意味着,都需要去更改这个类,这个类承担了太多的责任,这违背了我们的单一职责原则,增加新的管理类别,需要修改这个类,违背了开放-封闭原则。因为有多个管理类别,所以我们可以把这些管理这的类别分别做成管理者的子类,这就可以利用多态性来化解分支带来的僵化。针对经理无权,上报总监,总监无权再上报总经理这样的功能,我们可以把用户的请求传递。

这其实就是一种设计模式-- 职责链模式

职责链模式

职责链模式: 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止

这里发出这个请求的客户端并不知道这当中的哪一个对象最终处理这个请求,这样系统的更改可以在不影响客户端的情况下动态的重新组织和分配责任。

职责链结构图:

在这里插入图片描述
Handler类,定义一个处理请示的接口

abstract class Handler{ 
        protected  Handler successor;
        //设置继任者
        public void setSuccessor(Handler successor){
            this.successor = successor;
        }
        public abstract void handlerRequest(int request);
  }

ConcreteHandler类,具体处理者类,处理它所负责的请求,可访问它的后继者,如果可处理该请求,就处理之,否则就将该请求转发给它的后继者。
ConcreteHandler1 ,当请求数为0~10则有权处理,否则转到下一位

//处理请求为0-10
 class ConcreteHandler1 extends Handler{
      @Override
      public void handlerRequest(int request) {
          if(request>0 && request<10){
              System.out.println(this.getClass().getSimpleName() + "处理请求" + request);
          }else if(successor != null){
              successor.handlerRequest(request);
          }
      }
  }
  //处理请求为10-20
  class ConcreteHandler2 extends Handler{
      @Override
      public void handlerRequest(int request) {
          if(request >=10 && request < 20){
              System.out.println(this.getClass().getSimpleName() + ",处理请求" + request);
          }else if(successor != null){
              successor.handlerRequest(request);
          }
      }
  }
  //处理请求为20-30
  class ConcreteHandler3 extends Handler{
      @Override
      public void handlerRequest(int request) {
          if(request >=20 && request < 30){
              System.out.println(this.getClass().getSimpleName() + ",处理请求" + request);
          }else if(successor != null){
              successor.handlerRequest(request);
          }
      }
  }

客户端代码,向链上的具体处理者对象提交请求

   public static void main(String[] args) {
        Handler h1 = new ConcreteHandler1();
        Handler h2 = new ConcreteHandler2();
        Handler h3 = new ConcreteHandler3();
        //设置职责,上家和下家
        h1.setSuccessor(h2);
        h2.setSuccessor(h3);
        int[] requests = {2,5,14,22,18,3,27,20};
        for(int X : requests){
            h1.handlerRequest(X);
        }
    }

职责链的好处

职责链模式中最关键的是当客户提交一个请求时,请求是沿链传递直至有一个ConcreteHandler对象负责处理它。 这样做的好处就是不用管那个对象来处理,反正该请求会被处理。这就使得接收者和发送者都没有对方的明确信息,且链中的对象自己也并不知道链的结构。结果是职责链可简化对象的相互连接,它们仅需保持一个指向其后继者的引用,而不需要保持它所有的候选接受者的引用。这也就大大降低了耦合度了 。另外我们是在客户端来定义链的结构,也就是说,我可以随时地增加或修改处理一个请求的结构。增强了给对象指派职责的灵活性。 但是需要注意一个请求极有可能到了链的末端都得不到处理,或者因为没有正确配置而得不到处理。 所以我们需要事前考虑全面。

加薪代码重构

Request请求类与原来一样。

	//管理者抽象类
  abstract class Manager{
        protected String name;
        public Manager(String name){
            this.name = name;
        }
        //设置管理者上级
        protected Manager superior;
        public void setSuperior(Manager superior){
            this.superior = superior;
        }
        
        //请求申请
        public abstract void requestApplications(Request request);
    }

经理类就可以去继承这个‘管理者’类,只需重写‘申请请求’的方法就可以了

 //普通经理类
    class CommonManager extends Manager{
        public CommonManager(String name){
            super(name);
        }
        @Override
        public void requestApplications(Request request) {
            if(request.getRequestType() == "请假" && request.getNumber() <= 2) {
                System.out.println(this.name + ": " + request.getRequestContent() + "数量 : " + request.getNumber() + "天,被批准");
            }else{
                if(this.superior != null){
                    this.superior.requestApplications(request);
                }
            }
        }
    }

总监同样继承管理者类

 //总监
    class Director extends Manager{
        public Director(String name){
            super(name);
        }
        @Override
        public void requestApplications(Request request) {
            if(request.getRequestType() == "请假" && request.getNumber() <= 5) {
                System.out.println(this.name + ": " + request.getRequestContent() + "数量 : " + request.getNumber() + "天,被批准");
            }else{
                if(this.superior != null){
                    this.superior.requestApplications(request);
                }
            }
        }
    }

总经理的权限就是全部都需要处理

 //总经理
    class GeneralManager extends Manager{
        public GeneralManager(String name) {
            super(name);
        }
        @Override
        public void requestApplications(Request request) {
            if(request.getRequestType() == "请假" && request.getNumber() <= 5) {
                System.out.println(this.name + ": " + request.getRequestContent() + "数量 : " + request.getNumber() + "天,被批准");
            }else if(request.getRequestType() == "加薪" && request.getNumber() <= 5000){
                System.out.println(this.name + ": " + request.getRequestContent() + "数量: " + request.getNumber() + "元,被批准");
            }else if(request.getRequestType() == "加薪" && request.getNumber() > 5000){
                System.out.println(this.name + ": " + request.getRequestContent() + "数量: " + request.getNumber() + "元,再说吧");
            }
        }
    }

由于我们把原来的一个管理者类改成了一个抽象类和三个具体类,此时类之间的灵活性就大大增加了,如果我们需要扩展新的管理类别,只需要增加子类就可以。比如这个例子增加一个‘集团总裁’类,是完全没有问题的,只需要修改‘总经理类’即可,并不影响其他代码。下面是客户端如何编写:

 public static void main(String[] args) {
        CommonManager manager = new CommonManager("老三");
        Director director = new Director("老二");
        GeneralManager generalManager = new GeneralManager("老大");
        manager.setSuperior(director);
        director.setSuperior(generalManager);

        Request request = new Request();
        request.setRequestType("请假");
        request.setRequestContent("小张请假");
        request.setNumber(1);
        manager.requestApplications(request);

        Request request2 = new Request();
        request2.setRequestType("请假");
        request2.setRequestContent("小张请假");
        request2.setNumber(4);
        manager.requestApplications(request2);

        Request request3 =new Request();
        request3.setRequestType("加薪");
        request3.setRequestContent("小张要加薪");
        request3.setNumber(5000);
        manager.requestApplications(request3);

        Request request4 = new Request();
        request.setRequestType("加薪");
        request.setRequestContent("小张要加薪");
        request.setNumber(10000);
        manager.requestApplications(request4);
    }

总结

以上就是本文全部内容,本文主要向大家介绍了设计模式中的职责链,通过申请加薪这一实例,引出职责链模式基本代码,最后改造加薪代码为责任链模式。感谢各位能够看到最后,如有问题,欢迎各位大佬在评论区指正,希望大家可以有所收获!创作不易,希望大家多多支持!

评论 58
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值