设计模式-责任链模式

什么是责任链模式

顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。

在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。

意图

解耦合。避免请求发送者与接收者耦合在一起,让多个接收者都有可能接收请求,将这些接收者连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。下游接收者没有资格处理就传给它的上游接收者。

主要解决

职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。
在简单的说就是:责任链是面向对象的实现,我们把多个情况拆封成多个接受者对象,根据顺序依次判断是接受者否有权限处理,如果有则处理,没有则继续传递,如果都没有则由最后的接受者抛出异常或者是他来进行默认的处理。

何时使用

在处理消息的时候会过滤很多道条件。

如何解决

拦截的类都实现统一接口。

应用实例

  1. 红楼梦中的"击鼓传花"。
  2. JS 中的事件冒泡。
  3. JAVA WEB 中 Apache Tomcat 对 Encoding 的处理,Struts2 的拦截器,jsp servlet 的 Filter。
  4. 员工请假时间

优点:

  1. 降低耦合度。它将请求的发送者和接收者解耦。
  2. 简化了对象。使得对象不需要知道链的结构。
  3. 增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
  4. 更改添加判断逻辑方便。

缺点:

  1. 不能保证请求一定被接收。
  2. 系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。 大量的请求判断会导致系统性能的极具下降。【这个在文章最后会详细解释说明】
  3. 可能不容易观察运行时的特征,有碍于除错。

使用场景:

  1. 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
  2. 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
  3. 可动态指定一组对象处理请求。

示例于对比

通过是否使用了责任链的代码来直观感受一下之间的区别 。

代码业务逻辑

员工请假
这里的代码是一员工请假来实现的。
现在说一下员工请假的业务
员工请假会经过不同的上级批准:小于两天的假,经理有权限;小于五天的假,总监有权限批注;大于五天的假只有总监才有资格处理。

没有使用责任链

示例涉及到的类

  1. 创建请求实体 ApplyRequest
  2. 创建处理判断逻辑的类:Manager
  3. 测试:Test
    在这里插入图片描述

没有使用责任链的代码

  1. 创建请求实体 ApplyRequest
/**
 * @Description: 申请请求
 * @Author: lick
 * @CreateDate: 2019/11/16$ 22:22$
 * @Version: 1.0
 */
public class ApplyRequest {
    //  申请类型
    private String requestType;

    //  申请内容
    private String requestContent;

    //  申请数量
    private int appNumber;

    public String getRequestType() {
        return requestType;
    }

    public void setRequestType(String requestType) {
        this.requestType = requestType;
    }

    public String getRequestContent() {
        return requestContent;
    }

    public void setRequestContent(String requestContent) {
        this.requestContent = requestContent;
    }

    public int getAppNumber() {
        return appNumber;
    }

    public void setAppNumber(int appNumber) {
        this.appNumber = appNumber;
    }
}
  1. 创建处理判断逻辑的类:Manager
/**
 * @Description: 管理层
 * @Author: lick
 * @CreateDate: 2019/11/16$ 22:25$
 * @Version: 1.0
 */
public class Manager {
    protected String name;

    //  set  构造

    public Manager(String name) {
        this.name = name;
    }

    public void requestHandle(ApplyRequest applyRequest, String level){
        if("经理".equals(level)){
            if("请假".equals(applyRequest.getRequestType())
                    && applyRequest.getAppNumber() <= 2){
                System.out.println("请假数量小于等于2天,经理"+this.name+" 批准");
            } else {
                System.out.println("经理"+this.name+"无权处理");
            }
        } else if("总监".equals(level)){
            if("请假".equals(applyRequest.getRequestType())
                    && applyRequest.getAppNumber() <= 5){
                System.out.println("请假数量小于等于=5天,总监"+this.name+" 批准");
            } else {
                System.out.println("总监"+this.name+"无权处理");
            }
        } else if("总经理".equals(level)){
            if("请假".equals(applyRequest.getRequestType())){
                System.out.println("请假被总经理"+this.name+"批准");
            } else if("加薪".equals(applyRequest.getRequestType())){
                if(applyRequest.getAppNumber() <= 300){
                    System.out.println("加薪"+applyRequest.getAppNumber()+",给总经理"
                    +this.name+"批准");
                } else {
                    System.out.println("总经理"+this.name+"说要什么钱,要有梦想");
                }
            }
        }
    }
}
  1. 测试:Test
/**
 * @Description: java类作用描述
 * @Author: lick
 * @CreateDate: 2019/11/16$ 22:36$
 * @Version: 1.0
 */
public class Test {

    public static void main(String[] args) {
        Manager jingli = new Manager("Fame老师");
        Manager zongjian = new Manager("ShineYork老师");
        Manager zongjingli = new Manager("Pack老师");

        ApplyRequest request = new ApplyRequest();
        request.setRequestType("加薪");
        request.setRequestContent("Zero老师请求加薪");
        request.setAppNumber(200);

        jingli.requestHandle(request, "经理");
        zongjian.requestHandle(request, "总监");
        zongjingli.requestHandle(request, "总经理");
    }

}

从上面可以看出,Manager 中的代码十分臃肿,这么简单的逻辑全在一个类中,一个方法中。如果逻辑更加复杂那岂不是一个方法几百上千上万行的代码。如果不同的判断涉及到不同的private变量,那岂不是可读性又变得更加低了,就算是抽成同类不同的方法也会感觉十分的臃肿。这样的代码是十分的不易修改和阅读,当需求变化时你可能会需要一杯红牛陪伴加班。。。。

使用责任链的代码

下面看看责任链的处理:

涉及到的类

  1. 请求实体:ApplyRequest
  2. 创建父类:ManagnSixsta
  3. 将不同的经理职位对象化【记住万物皆对象】,创建管理层的类:CommonManager,GeneraManager,MajordomoManager
  4. 测试:ChainTest
    在这里插入图片描述

代码如下

  1. 请求实体:ApplyRequest

/**
 * @Description: 申请请求
 * @Author: lick
 * @CreateDate: 2019/11/16$ 22:22$
 * @Version: 1.0
 */
public class ApplyRequest {
    //  申请类型
    private String requestType;

    //  申请内容
    private String requestContent;

    //  申请数量
    private int appNumber;

    public String getRequestType() {
        return requestType;
    }

    public void setRequestType(String requestType) {
        this.requestType = requestType;
    }

    public String getRequestContent() {
        return requestContent;
    }

    public void setRequestContent(String requestContent) {
        this.requestContent = requestContent;
    }

    public int getAppNumber() {
        return appNumber;
    }

    public void setAppNumber(int appNumber) {
        this.appNumber = appNumber;
    }
}

  1. 创建父类:ManagnSixstar
/**
 * @Description: 管理层抽象类
 * @Author: lick
 * @CreateDate: 2019/11/16$ 22:49$
 * @Version: 1.0
 */
public abstract class ManagnSixstar {
    //  管理者名字
    protected String name;

    //  上级领导  null  总经理
    protected ManagnSixstar superior;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public ManagnSixstar getSuperior() {
        return superior;
    }

    public void setSuperior(ManagnSixstar superior) {
        this.superior = superior;
    }

    /**
     *  请求处理接口
     * @param applyRequest
     */
    public abstract void applyRequestHandle(ApplyRequest applyRequest);
}

  1. 将不同的经理职位对象化【记住万物皆对象】,创建管理层的类:CommonManager,GeneraManager,MajordomoManager

/**
 * @Description: 管理层 -- 经理
 * @Author: lick
 * @CreateDate: 2019/11/16$ 22:55$
 * @Version: 1.0
 */
public class CommonManager extends ManagnSixstar{

    public void applyRequestHandle(ApplyRequest applyRequest) {
        if("请假".equals(applyRequest.getRequestType())
                && applyRequest.getAppNumber() <= 2){
            System.out.println("请假数量小于等于2天,经理"+this.name+" 批准");
        } else {
         //   System.out.println("经理"+this.name+"无权处理");
            if(superior != null){
                superior.applyRequestHandle(applyRequest);
            }
        }
    }
}

/**
 * @Description: 管理层 -- 总经理
 * @Author: lick
 * @CreateDate: 2019/11/16$ 23:00$
 * @Version: 1.0
 */
public class GeneraManager extends ManagnSixstar{
    public void applyRequestHandle(ApplyRequest applyRequest) {
        if("请假".equals(applyRequest.getRequestType())){
            System.out.println("请假被总经理"+this.name+"批准");
        } else if("加薪".equals(applyRequest.getRequestType())){
            if(applyRequest.getAppNumber() <= 300){
                System.out.println("加薪"+applyRequest.getAppNumber()+",给总经理"
                        +this.name+"批准");
            } else {
                System.out.println("总经理"+this.name+"说要什么钱,要有梦想");
            }
        }
    }
}

/**
 * @Description: 管理层 -- 总监
 * @Author: lick
 * @CreateDate: 2019/11/16$ 22:58$
 * @Version: 1.0
 */
public class MajordomoManager extends ManagnSixstar{
    public void applyRequestHandle(ApplyRequest applyRequest) {
        if("请假".equals(applyRequest.getRequestType())
                && applyRequest.getAppNumber() <= 5){
            System.out.println("请假数量小于等于=5天,总监"+this.name+" 批准");
        } else {
         //   System.out.println("总监"+this.name+"无权处理");
            if(superior != null){
                superior.applyRequestHandle(applyRequest);
            }
        }
    }
}

  1. 测试:ChainTest
/**
 * @Description: java类作用描述
 * @Author: lick
 * @CreateDate: 2019/11/16$ 23:02$
 * @Version: 1.0
 */
public class ChainTest {
    public static void main(String[] args) {
        CommonManager jingli = new CommonManager();
        MajordomoManager zongjian = new MajordomoManager();
        GeneraManager zongjingli = new GeneraManager();

        //  设置你是谁
        jingli.setName("Fame老师");
        //  设置上层领导是谁
        jingli.setSuperior(zongjian);

        //  设置你是谁
        zongjian.setName("ShineYork老师");
        //  设置上层领导是谁
        zongjian.setSuperior(zongjingli);

        //  设置你是谁
        zongjingli.setName("Pack老师");
        //  设置上层领导是谁
        zongjingli.setSuperior(zongjingli);

        ApplyRequest request = new ApplyRequest();
        request.setRequestType("加薪");
        request.setRequestContent("Zero老师请假加薪");
        request.setAppNumber(200);
        //  重点
        jingli.applyRequestHandle(request);

        System.out.println("=======================================");
        System.out.println("=======================================");
        System.out.println("=======================================");

        ApplyRequest request2 = new ApplyRequest();


        request2.setRequestType("请假");
        request2.setRequestContent("Zero老师请假");
        request2.setAppNumber(6);
        jingli.applyRequestHandle(request2);
    }
}

上面的代码是责任链的代码,虽然代码变多了但是这种代码确实有很高的可读性,可改性(解耦)。
但是也存在一个缺点:虽然可读性的提升了,但是某些情况下会导致程序性能的消耗。假如责任链比较长,而且每次都是最后的接受对象来处理这个事件消息,大量的这种情况会导致程序性能严重降低,比如双十一的时候用户请求极具上升就会导致这个问题。
由此可得不是所有的情况都要是用责任链模式。设计模式的初衷是优化代码优化程序,当他不能在你需要的情况下的到提升是可以不是用设计模式的。不是所有的情况都要使用设计模式,我们更多的需要思考是否有用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值