设计模式之——责任链设计模式

来源:互联网 发布:urllib.request json 编辑:程序博客网 时间:2024/06/05 17:17

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

该模式在生活中很常见,比如:汽车制造、物流分拣、食品加工、质量检测等等,生活中更多的是这样的非纯责任模式,也就是说,每个节点都会根据自己的职责操作自己对应的部分,然后转交下一节点处理;也有纯责任模式,比如质检,一旦某个节点出问题直接不合格并打回。这种模式一般是从低等级往高等级层层请求。

我们来举个团建经费申请的例子:

场景设定:

项目经理(500) - 部门主管(1000) - 总经理(2000) - 老板(2000~5000)

首先抽象出经理,并创建链的连接关系

package com.zndroid.dm.ChainOfResponseModel;/** * Created by luzhenyu on 2017/9/18. *//**抽象出可处理的对象,并提供‘链’的关联和具体类的处理请求*/public abstract class Manager {    public abstract void request(int mount);//请求入口    public void setNextManager(Manager nextManager) {        this.nextManager = nextManager;    }    protected Manager nextManager;//提供链关联    public void done() {        System.out.println("[OK...]");    }}

具体节点

package com.zndroid.dm.ChainOfResponseModel.impl;import com.zndroid.dm.ChainOfResponseModel.Manager;/** * Created by luzhenyu on 2017/9/18. */public class ProjectManager extends Manager {    @Override    public void request(int mount) {        if (mount <= 500) {            System.out.println("项目经理审批通过,申请金额:" + mount);            done();            return;        }        else {            System.out.println("金额超出项目经理的范围,开始转交上级处理...");            nextManager.request(mount);        }    }}
package com.zndroid.dm.ChainOfResponseModel.impl;import com.zndroid.dm.ChainOfResponseModel.Manager;/** * Created by luzhenyu on 2017/9/18. */public class DepartmentManager extends Manager {    @Override    public void request(int mount) {        if (mount > 500 && mount <= 1000) {            System.out.println("部门主管审批通过,申请金额:" + mount);            done();            return;        }        else {            System.out.println("金额超出部门主管的范围,开始转交上级处理...");            nextManager.request(mount);        }    }}
package com.zndroid.dm.ChainOfResponseModel.impl;import com.zndroid.dm.ChainOfResponseModel.Manager;/** * Created by luzhenyu on 2017/9/18. */public class GeneralManager extends Manager {    @Override    public void request(int mount) {        if (mount > 1000 && mount <= 2000) {            System.out.println("总经理审批通过,申请金额:" + mount);            done();            return;        }        else {            System.out.println("金额超出总经理的范围,开始转交上级处理...");            nextManager.request(mount);        }    }}
package com.zndroid.dm.ChainOfResponseModel.impl;import com.zndroid.dm.ChainOfResponseModel.Manager;/** * Created by luzhenyu on 2017/9/18. */public class BossManager extends Manager {    @Override    public void request(int mount) {        if (mount > 2000 && mount <= 5000) {            System.out.println("老板审批通过,申请金额:" + mount);            done();            return;        }        else {            System.out.println("老板哭穷中...");        }    }}
使用如下
/**         * 职责链模式         * 使多个对象都有可能处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。         *         * 往往它是一个从最低级到上层的请求方式,职责链模式可以灵活的改变内部的传递规则,每个人可以动态的制定自己的继承者。         * 如果初始层级暂时不在或消失,请求也可以直接发送给其他层级,后续职责链还会继续进行。而且可以随时增加和修改处理一个请求的结构,增加了给对象指派的职责的灵活性。         *         * 优点:         * 调用者不需知道具体谁来处理请求,也不知道链的具体结构,降低了节点域节点的耦合度;可在运行时动态修改链中的对象职责,增强了给对象指派职责的灵活性;         * 缺点:         * 没有明确的接收者,可能传到链的最后,也没得到正确的处理;系统性能会受到影响;代码调试比较繁琐。         *         * 具体应用:         * OA系统;在java中的实际应用有Servlet中的过滤器(Filter);Struts2的拦截器(Interceptor),生活中大部分流程还是不纯的责任链,也就是每个节点的对象都有可能         * 做了对应的操作,高层次的操作要以低层次的为依据,比如:公司请假肯定要部门经理先同意才能走到下一级,而不是说,部门经理不同意就会走到老板那。         * */        //下面来模拟一下公司的团建申请        //比方说现在有三个老总可以处理团建申请,他们的可以批示的金额分变为:        //项目经理(500) - 部门主管(1000) - 总经理(2000) - 老板(2000~5000)        //创建节点:        ProjectManager projectManager = new ProjectManager();        DepartmentManager departmentManager = new DepartmentManager();        com.zndroid.dm.ChainOfResponseModel.impl.GeneralManager  generalManager= new com.zndroid.dm.ChainOfResponseModel.impl.GeneralManager();        BossManager bossManager = new BossManager();        //建立链接:        projectManager.setNextManager(departmentManager);        departmentManager.setNextManager(generalManager);        generalManager.setNextManager(bossManager);        projectManager.request(3000);        log("----------------我是分割线-----------------");
运行结果:

[ ======================================== ]
金额超出项目经理的范围,开始转交上级处理...
金额超出部门主管的范围,开始转交上级处理...
金额超出总经理的范围,开始转交上级处理...
老板审批通过,申请金额:3000
[OK...]
[ ----------------我是分割线----------------- ]
[ ======================================== ]



【欢迎上码】

【微信公众号搜索 h2o2s2】