常用设计模式系列(十八)-责任链模式

常用设计模式系列(十八)-责任链模式

第一节

前言

最近小编走在下班的路上,老是碰见一栋建筑,它的外墙装饰了灯带,灯带的内容。。。各位自己看吧。

咳咳,看着这个建筑的灯带还不错吧,简洁大方。可是在我们程序员眼里:这个建筑物的灯带主要由"0"和"1"组成,这两栋楼的灯光从上到下为"011001",二进制转换为十进制就是25。这个25意味着什么?意味着现在是2025年,但是一切还是个0,小编着实有点扎心,马上也踏上奔三的节奏了,自己从一无所有到一事无成,生活的希望不就是一个又一个挫折;你以为自己很失败,其实你认为的是对的。干了这碗毒鸡汤,所谓感情深一口闷,哈哈哈。

进入今天的正题,今天讲解行为型设计模式------职责链模式,职责链模式也叫责任链模式,"职责"一词,我们可以采用见名知意的方式去理解,即承担职责并完成职责。

在小时候上学时,学校老师提倡购买教辅资料,需要500块钱,那么此时购买教辅的责任在你的身上,由于自己没钱,你去向你的父亲申请资金,你要了700块钱说要买资料,此时,责任落在了你的父亲身上,你父亲发现自己每个月生活费也就可怜巴巴的二百块,于是你的父亲颤巍巍的向你的母亲发出了申请,说孩子买教材要1千块,此时责任就落到了你母亲身上,你母亲审批后选择把钱直接打给到老师,发现只需要500块的材料费时,你和你的父亲都遭受到了毒打,虽然你和父亲都挨了打,但是此时这个任务已经完成,老师只需要发起通知,具体的实现与审批过程他不需要了解,整个过程形成一个链条,这个模式就是职责链模式。

第二节

责任链模式

概念

责任链(Chain of

Responsibility)模式的定义:为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。

特征

在责任链模式中,客户只需要将请求发送到责任链上即可,无须关心请求的处理细节和请求的传递过程,请求会自动进行传递。所以责任链将请求的发送者和请求的处理者解耦了。

责任链分类

纯的责任链:纯的责任链模式要求一个具体的对象只能在两种行为中选择一个,要么承担全部责任,要么把责任推给下家,不允许出现具体处理者承担一部分责任后再传递给下家,且最终必须被某一个对象所接收,不能出现某个请求未被任何一个处理者对象处理的情况,本文代码演示的就是纯的责任链。

不纯的责任链:允许某个请求被某个具体处理者部分处理后再向下传递,或者认为一个具体处理者处理后,他的后续处理者可以继续处理该请求,而且一个请求可以最终不被任何具体处理者对象接收并处理,我们在进行web开始时见到的过滤器,使用的就是不纯的责任链模式。

职责链模式组成:

UML图:

第三节

场景分析及代码实现

场景举例

我们就按照开头的买教辅材料的人物关系进行讲述。买教材风波之后,母亲进行了反思,是不是对你们爷儿两个管的太严了,最终决定拿出来一部分钱用来给你和父亲做支配,但是前提只能是用于你的学习,父亲作为监督人,来监督钱的走向,故定下来规矩

场景分析

1.一家人的抽象,则为抽象处理类Handler

2.孩子即具体处理者中的一个,则编写具体处理者类ChildHandler

3.父亲为第二处理者,则编写具体处理者FatherHandler

4.母亲为第三处理者,则编写具体处理者MontherHandler

5.购买的物品即商品类

代码实现

1.编写商品类

复制代码
package com.yang.chainofresponsibility;


/**
 * @ClassName Shop
 * @Description 商品类
 * @Author IT小白架构师之路
 * @Date 2021/1/27
 * @Version 1.0
 **/
public class Shop {
    //商品名称
    private String name;
    //商品价格
    private double price;
    //构造
    public Shop(String name,double price){
        this.name = name;
        this.price = price;
    }


    public String getName() {
        return name;
    }


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


    public double getPrice() {
        return price;
    }


    public void setPrice(double price) {
        this.price = price;
    }
}

2.编写抽象处理类Handler

复制代码
package com.yang.chainofresponsibility;


/**
 * @ClassName Handler
 * @Description 抽象处理者
 * @Author IT小白架构师之路
 * @Date 2021/1/27
 * @Version 1.0
 **/
public abstract class Handler {
    //下一个处理者
    protected Handler successor;


    public Handler getSuccessor() {
        return successor;
    }


    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }


    public abstract void handlerRequest(Shop shop);
}

3.编写具体处理者类ChildHandler

复制代码
package com.yang.chainofresponsibility;


/**
 * @ClassName ChildHandler
 * @Description 小孩
 * @Author IT小白架构师之路
 * @Date 2021/1/27
 * @Version 1.0
 **/
public class ChildHandler extends Handler{
    //处理类
    public void handlerRequest(Shop shop) {
        double price = shop.getPrice();
        if(price<=100){
            System.out.println("无须报备,直接花钱("+price+")购买"+shop.getName());
        }else{
            System.out.println("孩子向上报备");
            this.successor.handlerRequest(shop);
        }
    }
}

4.编写具体处理者FatherHandler

复制代码
package com.yang.chainofresponsibility;


/**
 * @ClassName FatherHandle
 * @Description 父亲审核
 * @Author IT小白架构师之路
 * @Date 2021/1/27
 * @Version 1.0
 **/
public class FatherHandler  extends Handler{
    //处理类
    public void handlerRequest(Shop shop) {
        double price = shop.getPrice();
        if(price>100 && price <= 500){
            System.out.println("父亲审核,允许花钱("+price+")购买"+shop.getName());
        }else{
            System.out.println("父亲向上报备");
            this.successor.handlerRequest(shop);
        }
    }
}

5.编写具体处理者MontherHandler

复制代码
package com.yang.chainofresponsibility;


/**
 * @ClassName MontherHander
 * @Description 母亲审核类
 * @Author IT小白架构师之路
 * @Date 2021/1/27 15:14
 * @Version 1.0
 **/
public class MontherHander extends Handler{
    //处理类
    public void handlerRequest(Shop shop) {
        double price = shop.getPrice();
        System.out.println("母亲审核,超过500元拒绝");
    }
}

6.编写客户端进行测试

复制代码
package com.yang.chainofresponsibility;


/**
 * @ClassName Client
 * @Description 客户端
 * @Author IT小白架构师之路
 * @Date 2021/1/27
 * @Version 1.0
 **/
public class Client {
    public static void main(String[] args) {
        //小孩
        Handler childHandle = new ChildHandler();
        //父亲
        Handler fatherHandle = new FatherHandler();
        //母亲
        Handler motherHandle = new MontherHander();
        //孩子的上一级审核人为父亲
        childHandle.setSuccessor(fatherHandle);
        //父亲的上一级审核人
        fatherHandle.setSuccessor(motherHandle);
        //购买西游记
        System.out.println("----------------------开始-------------------------");
        Shop book = new Shop("名著《西游记》",50);
        childHandle.handlerRequest(book);
        System.out.println("----------------------分割线-------------------------");
        //购买玩具赛车
        Shop car = new Shop("F1电动玩具赛车",288);
        childHandle.handlerRequest(car);
        System.out.println("----------------------分割线-------------------------");
        //购买手机
        Shop mobile = new Shop("小米手机",1999);
        childHandle.handlerRequest(mobile);
        System.out.println("----------------------结束-------------------------");
    }
}

7.测试结果如下

复制代码
----------------------开始-------------------------
无须报备,直接花钱(50.0)购买名著《西游记》
----------------------分割线-------------------------
孩子向上报备
父亲审核,允许花钱(288.0)购买F1电动玩具赛车
----------------------分割线-------------------------
孩子向上报备
父亲向上报备
母亲审核,超过500元拒绝
----------------------结束-------------------------

第四节

优缺点及适用场景

优点:

1.责任链可以让客户端对象无需知道是其他哪几个对象处理其请求,对象仅需知道该请求会被处理即可,接收者和发送者都没有对方的明确信息,并且链中的对象不需要知道"链"的结构,由客户端负责"链"的创建,降低了系统的耦合度。

2.对象请求处理仅需维持一个指向下一个处理者的引用,不需要维持他对所有的候选处理者的引用,简化对象间的关系。

3.责任链在给对象分配职责时,可以带来更多的灵活性,可以在运行时对该链进行动态的添加或者修改来增加或者改变一个请求的职责。

4.增加一个新的具体请求者时,不需要修改原来的代码,只需要客户端重新建立"链"即可。

缺点:

1.一个请求如果没有明确接收者,那么也就不能保证它一定会被处理,该请求可能一直到链的末端都得不到处理;一个请求也可能因责任链没有配置正确而得不到处理

2.对于较长的责任链,请求的处理可能涉及多个处理对象,系统性能可能会被印象,代码维护调试会难度增加

3.建立责任链错误时,会增加死循环的调用风险。

适用场景:

1.当一个请求需要被多个处理者请求的场景,可以是一级级审批,也可以是一级一级处理后再审批的场景,这个处理时机在运行时刻再确定。

2.在不明确接收者的情况下,向多个对象中的一个提交请求的场景。

3.可动态指定一组具体处理者对象用来处理请求,客户端可以动态的创建责任链来处理请求,还能改变、增加处理者顺序、数量的场景下。

觉得不错的话,点个关注再走吧

相关推荐
易元4 天前
模式组合应用-享元模式
后端·设计模式
vker5 天前
第 2 天:工厂方法模式(Factory Method Pattern)—— 创建型模式
java·后端·设计模式
vker6 天前
第 1 天:单例模式(Singleton Pattern)—— 创建型模式
java·设计模式
晨米酱6 天前
JavaScript 中"对象即函数"设计模式
前端·设计模式
数据智能老司机7 天前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机7 天前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机7 天前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机7 天前
精通 Python 设计模式——性能模式
python·设计模式·架构
使一颗心免于哀伤7 天前
《设计模式之禅》笔记摘录 - 21.状态模式
笔记·设计模式
数据智能老司机7 天前
精通 Python 设计模式——创建型设计模式
python·设计模式·架构