设计模式-行为型-职责链设计模式

一、简介

职责链设计模式是属于经典设计模式中行为型设计模式里的一种设计模式。其实这种模式
在现实生活中很多地方出现,比如说:

1.多人打牌:
    上家出牌后,出牌请求到达下家,下家出牌后,下下家获得出牌机会, 在一轮后如果无人出牌,则可以从
    新下一轮出牌,这样一个场景,其实就是职责链模式的原型。

2.审批流程:
    再比如,一个公司的采购单审批流程,如果采购单总价在5万RMB,那么主任审核即可,    如果5-10万RMB
    由副董事长审批,10-50万由董事长审批,>=50万则由董事会审批。每一个节点只负责职责内的订单额度,
    如果自己没有权限,则给自己的下节点进行转发申请。

二、模式实现

上面的两个场景我们调选一个进行实现,我们就用进阶的方式从最简单的设计一步一步往目标设计走。这里我选择2,审批流程的实现进行设计。初始代码如下:

原始设计

class AuditHandler {

    // @TODO 递交采购单给主任
    public void sendRequestToDirector(PurchaseRequest request) {
        if (request.getAmount() < 50000) {
            // @TODO 主任可审批该采购单
            this.handleByDirector(request);
        } else if (request.getAmount() < 100000) {
            // @TODO 副董事长可审批该采购单
            this.handleByVicePresident(request);
        } else if (request.getAmount() < 500000) {
            // @TODO 董事长可审批该采购单
            this.handleByPresident(request);
        } else {
            // @TODO 董事会可审批该采购单
            this.handleByCongress(request);
        }
    }

    // @TODO 主任审批采购单
    public void handleByDirector(PurchaseRequest request) {
        //代码省略
    }

    // @TODO 副董事长审批采购单
    public void handleByVicePresident(PurchaseRequest request) {
        //代码省略
    }

    // @TODO 董事长审批采购单
    public void handleByPresident(PurchaseRequest request) {
        //代码省略
    }

    // @TODO 董事会审批采购单
    public void handleByCongress(PurchaseRequest request) {
        //代码省略
    }
}

class PurchaseRequest {

    private long amount;

    public long getAmount() {
        return amount;
    }
}

上面这种设计方式可以处理完成相应的业务,但违反了:单一职责原则,开闭原则。一个类集中了过多的职责,如果一旦需要在期间进行扩展一个角色进行审批,就需要改动原有的代码。并且这种设计模式是无法实现使用方可定制化的,因为都写死了。

升级设计

为了解决上面设计的原则缺陷,我们进行进行设计升级,把多个职责进行拆分,独立出单个处理类。使用一个抽象的处理类,实现各个链节点的关联与处理细节

/**
 * @author chandlerHuang
 * @description @TODO 抽象处理类
 * @date 2020/3/27
 */
public abstract class AbstractHandler {

    // @TODO 处理连接
    protected AbstractHandler abstractHandler;

    public AbstractHandler(AbstractHandler abstractHandler) {
        this.abstractHandler = abstractHandler;
    }

    public void setAbstractHandler(AbstractHandler abstractHandler) {
        this.abstractHandler = abstractHandler;
    }

    public abstract void handle(PurchaseRequest request);
}

class Handler extends AbstractHandler{

    // 所指岗位
    private String position;

    // 处理金额上限
    private double amount;

    public void setPosition(String position) {
        this.position = position;
    }

    public void setAmount(long amount) {
        this.amount = amount;
    }

    public Handler(AbstractHandler abstractHandler,String position, long amount) {
        super(abstractHandler);
        this.amount = amount;
        this.position = position;
    }

    @Override
    public void handle(PurchaseRequest request) {
        if(this.amount>request.getAmount()){
            // @TODO 处理请求
           System.out.println(this.position+"审核处理采购单:"+request.getNumber() +"->"+ request.getPurpose()+" 购买金额:"+request.getAmount());
        }else {
            // @TODO 交给下一节点处理
            this.abstractHandler.handle(request);
        }
    }
}

class PurchaseRequest {

    //采购金额
    private double amount;

    //采购单编号
    private int number;

    //采购目的、备注
    private String purpose;

    public PurchaseRequest(double amount, int number, String purpose) {
        this.amount = amount;
        this.number = number;
        this.purpose = purpose;
    }

    public double getAmount() {
        return amount;
    }

    public int getNumber() {
        return number;
    }

    public String getPurpose() {
        return purpose;
    }

    public void setAmount(double amount) {
        this.amount = amount;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    public void setPurpose(String purpose) {
        this.purpose = purpose;
    }
}

这里面对于责任链的构建是交给了使用方,这样极大的增强了这个设计的代码复用率,可扩展性以及流程的可变性。

这里我们来演示一下使用方式,构建流程处理链。

客户端调用

/**
 * @author chandlerHuang
 * @description @TODO
 * @date 2020/3/27
 */
public class Test {

    public static void main(String[] args) {
        // @TODO 构建流程链
        Handler handler = init();

        // @TODO 构建采购单
        List<PurchaseRequest> requests = buildRequest();

        // @TODO 处理
        requests.forEach(request->{
            handler.handle(request);
        });
    }

    private static List<PurchaseRequest> buildRequest() {

        List<PurchaseRequest> datas = new ArrayList<>(4);
        PurchaseRequest data1 = new PurchaseRequest(39000.00,10001,"购买云服务器");

        PurchaseRequest data2 = new PurchaseRequest(89000.00,10002,"采购办公电脑与办公用品");

        PurchaseRequest data3 = new PurchaseRequest(490430.87,10003,"分公司装修装潢采购");

        PurchaseRequest data4 = new PurchaseRequest(1189490430,10004,"购置地皮建厂");

        datas.add(data1);
        datas.add(data2);
        datas.add(data3);
        datas.add(data4);

        return datas;
    }

    private static Handler init() {
        // 董事会节点
        Handler handler4 = new Handler(null,"董事会",Double.MAX_VALUE);
        // 董事长节点
        Handler handler3 = new Handler(handler4,"董事长",500000.00);
        // 副董事长节点
        Handler handler2 = new Handler(handler3,"副董事长", 100000.00);
        // 财务主任节点
        Handler handler = new Handler(handler2,"财务主任", 50000.00);
        return handler;
    }
}

上面的代码显示了,如果你需要调整节点,只需要在构建流程链内处理(客户端|使用方),而我们的设计方不需要进行改动,将发送方与处理方进行了解耦。无需关心具体处理节点。

职责链模式优点

1.职责链模式使得一个对象无须知道是其他哪一个对象处理其请求,对象仅需知道该请求会 被处理即可,接收者和发送者都没有对方的明确信息,且链中的对象不需要知道链的结构, 由客户端负责链的创建,降低了系统的耦合度。
2.请求处理对象仅需维持一个指向其后继者的引用,而不需要维持它对所有的候选处理者的 引用,可简化对象的相互连接。

职责链模式缺点

1.由于一个请求没有明确的接收者,那么就不能保证它一定会被处理,该请求可能一直到链 的末端都得不到处理;一个请求也可能因职责链没有被正确配置而得不到处理。
2.对于比较长的职责链,请求的处理可能涉及到多个处理对象,系统性能将受到一定影响, 而且在进行代码调试时不太方便。
3.如果建链不当,可能会造成循环调用,将导致系统陷入死循环。

合适使用场景

1.有多个对象可以处理同一个请求,具体哪个对象处理该请求待运行时刻再确定,客户端只 需将请求提交到链上,而无须关心请求的处理对象是谁以及它是如何处理的。
2.在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
3.可动态指定一组对象处理请求,客户端可以动态创建职责链来处理请求,还可以改变链中 处理者之间的先后次序。

三、思考题

上面设计处理责任链模式处理采购单审批。请各位读者采用职责链模式设计:标准斗地主程序.

原文地址:https://blog.51cto.com/4837471/2482514

时间: 2024-09-29 21:59:21

设计模式-行为型-职责链设计模式的相关文章

设计模式-行为型-职责链模式

职责链模式(Chain of Responsibility): 在现实生活中,常常会出现这样的事例:一个请求需要多个对象处理,但每个对象的处理条件或权限不同.如公司员工报销差旅费,可审批的领导有部分负责人.副总经理.总经理等,但每个领导能审批的金额是不同的,不同的金额需要找相应的领导审批,也就是说要报销必须先搞清楚需要谁来审批.职责链模式就是为了解决这样的问题产生的. 职责链模式,又叫责任链模式.是为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一个对象记住其下一个对象的引

设计模式 ( 十二 ) 职责链模式(Chain of Responsibility)(对象行为)

 设计模式(十二)职责链模式(Chain of Responsibility)(对象行为型) 1.概述 你去政府部门求人办事过吗?有时候你会遇到过官员踢球推责,你的问题在我这里能解决就解决.不能解决就推卸给另外个一个部门(对象).至于究竟谁来解决问题呢?政府部门就是为了能够避免屁民的请求与官员之间耦合在一起,让多个(部门)对象都有可能接收请求,将这些(部门)对象连接成一条链,而且沿着这条链传递请求.直到有(部门)对象处理它为止. 样例1:js的事件浮升机制 样例2: 2.问题 假设有多个对象都有

[设计模式-行为型]责任链模式(Chain of Responsibility)

概括 名称 Chain of Responsibility 结构 动机 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止. 适用性 有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定. 你想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求. 可处理一个请求的对象集合应被动态指定. 解析 形象比喻: 晚上去上英语课, 为了好开溜坐到了最后一排, 哇, 前面坐了好几个漂亮的MM 哎

Java设计模式之职责链设计模式

1.什么是-职责链设计模式 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任.Tomcat中的Filter就是使用了责任链模式,创建一个Filter除了要在web.xml文件中做相应配置外,还需要实现javax.servlet.Filter接口. 2.职责链设计模式

编程模式之十四----行为型----职责链模式

定义 避免把一个请求的发送者和接收者耦合在一起,使多个对象都有机会处理请求.将这个请求的多个接收着连接成一条链,并让请求沿着这个链传递下去,只到有一个结点能处理请求. 职责链模式中,链形成后,不一定非要有一个结点能够处理请求,也就是说,所有结点都可以处理一下再往下传,也可以都不处理,这样说来就比较灵活了. 组成 抽象处理者:AbstractHandler.维护一个对自身类型对象的引用,这个引用作为下一个具体的处理者.声明所有处理者都用到的方法,这个方法的作用是设置本处理者后面的一个处理者.另外声

设计模式(十二)职责链模式(Chain of Responsibility)(对象行为型)

1.概述 你去政府部门求人办事过吗?有时候你会遇到过官员踢球推责,你的问题在我这里能解决就解决,不能解决就推卸给另外个一个部门(对象).至于到底谁来解决这个问题呢?政府部门就是为了可以避免屁民的请求与官员之间耦合在一起,让多个(部门)对象都有可能接收请求,将这些(部门)对象连接成一条链,并且沿着这条链传递请求,直到有(部门)对象处理它为止. 例子1:js的事件浮升机制 例子2: 2.问题 如果有多个对象都有可能接受请求,如何避免避免请求发送者与接收者耦合在一起呢? 3.解决方案 职责链模式(Ch

javascript设计模式实践之职责链--具有百叶窗切换图片效果的JQuery插件(三)

在上一篇<javascript设计模式实践之模板方法--具有百叶窗切换图片效果的JQuery插件(二)>里,通过采用模板方法模式完成了切换效果对象的构建编写. 接下来就是完成各效果对象的调用和联动. 切换要求:当前图片显示指定时间后执行切换效果并切换下一张图片,最后一个切换后从头开始. 按照要求一个效果对象完成后要执行下一个,最后一个完成后要从头开始, 看上去就是一个带状态通知的环形列表,类似于这样的特征,可以采用职责链模式来构建. 职责链就是由不同的功能处理构成的链表,每一个功能处理作为一个

设计模式学习之职责链模式

1.定义: 职责连模式(Chain of Responsibility),使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这个对象练成一条链,并沿着链传递该请求,直到由一个对象处理它为止. 2.UML ConcreteHandler1.ConcreteHandler2 :具体处理者类,处理它所负责的请求,可访问它的后继者,如果可处理该请求,就处理之,否则就将该请求转发给他的后继者. 3.职责链的好处 关键在与当客户提交一个请求时,请求是沿着链传递直至由一个Concrea

大话设计模式Python实现-职责链模式

职责链模式(Chain Of Responsibility):使多个对象都有机会处理请求,从而避免发送者和接收者的耦合关系.将对象连成链并沿着这条链传递请求直到被处理 下面是一个设计模式的demo: 1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 __author__ = 'Andy' 5 """ 6 大话设计模式 7 设计模式--职责链模式 8 职责链模式(Chain Of Responsibility):使多个对象