本文继续介绍23种设计模式系列之职责链模式。
 
什么是链
1、链是一系列节点的集合。
2.、链的各节点可灵活拆分再重组。
 
职责链模式
使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系,
将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止。
 
角色
抽象处理者角色(Handler):定义出一个处理请求的接口。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。
具体处理者角色(ConcreteHandler):具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。
抽象处理者角色
  1. public abstract class Handler {
  2. /**
  3. * 持有后继的责任对象
  4. */
  5. protected Handler successor;
  6. /**
  7. * 示意处理请求的方法,虽然这个示意方法是没有传入参数的
  8. * 但实际是可以传入参数的,根据具体需要来选择是否传递参数
  9. */
  10. public abstract void handleRequest();
  11. /**
  12. * 取值方法
  13. */
  14. public Handler getSuccessor() {
  15. return successor;
  16. }
  17. /**
  18. * 赋值方法,设置后继的责任对象
  19. */
  20. public void setSuccessor(Handler successor) {
  21. this.successor = successor;
  22. }
  23. }

具体处理者角色

  1. public class ConcreteHandler extends Handler {
  2. /**
  3. * 处理方法,调用此方法处理请求
  4. */
  5. @Override
  6. public void handleRequest() {
  7. /**
  8. * 判断是否有后继的责任对象
  9. * 如果有,就转发请求给后继的责任对象
  10. * 如果没有,则处理请求
  11. */
  12. if(getSuccessor() != null)
  13. {
  14. System.out.println("放过请求");
  15. getSuccessor().handleRequest();
  16. }else
  17. {
  18. System.out.println("处理请求");
  19. }
  20. }
  21. }

客户端类

  1. public class Client {
  2. public static void main(String[] args) {
  3. //组装责任链
  4. Handler handler1 = new ConcreteHandler();
  5. Handler handler2 = new ConcreteHandler();
  6. handler1.setSuccessor(handler2);
  7. //提交请求
  8. handler1.handleRequest();
  9. }
  10. }
可以看出,客户端创建了两个处理者对象,并指定第一个处理者对象的下家是第二个处理者对象,而第二个处理者对象没有下家。然后客户端将请求传递给第一个处理者对象。
由于本示例的传递逻辑非常简单:只要有下家,就传给下家处理;如果没有下家,就自行处理。
因此,第一个处理者对象接到请求后,会将请求传递给第二个处理者对象。由于第二个处理者对象没有下家,于是自行处理请求。活动时序图如下所示。
 
 
 
应用
申请聚餐费用的管理,申请聚餐费用的大致流程一般是,由申请人先填写申请单,然后交给领导审批,如果申请批准下来,领导会通知申请人审批通过,然后申请人去财务领取费用,如果没有批准下来,领导会通知申请人审批未通过,此事也就此作罢。
不同级别的领导,对于审批的额度是不一样的,比如,项目经理只能审批500元以内的申请;部门经理能审批1000元以内的申请;而总经理可以审核任意额度的申请。
 
当某人提出聚餐费用申请的请求后,该请求会经由项目经理、部门经理、总经理之中的某一位领导来进行相应的处理,但是提出申请的人并不知道最终会由谁来处理他的请求,一般申请人是把自己的申请提交给项目经理,或许最后是由总经理来处理他的请求。申请人只要直接与项目经理交互就可以,其余的工作在黑盒中,究竟流程是怎样的,最后是由谁审批通过的,申请人无需关心。
 
 
 

抽象处理者角色类
  1. public abstract class Handler {
  2. /**
  3. * 持有下一个处理请求的对象
  4. */
  5. protected Handler successor = null;
  6. /**
  7. * 取值方法
  8. */
  9. public Handler getSuccessor() {
  10. return successor;
  11. }
  12. /**
  13. * 设置下一个处理请求的对象
  14. */
  15. public void setSuccessor(Handler successor) {
  16. this.successor = successor;
  17. }
  18. /**
  19. * 处理聚餐费用的申请
  20. * @param user    申请人
  21. * @param fee    申请的钱数
  22. * @return        成功或失败的具体通知
  23. */
  24. public abstract String handleFeeRequest(String user , double fee);
  25. }

具体处理者角色

  1. public class ProjectManager extends Handler {
  2. @Override
  3. public String handleFeeRequest(String user, double fee) {
  4. String str = "";
  5. //项目经理权限比较小,只能在500以内
  6. if(fee < 500)
  7. {
  8. //为了测试,简单点,只同意张三的请求
  9. if("张三".equals(user))
  10. {
  11. str = "成功:项目经理同意【" + user + "】的聚餐费用,金额为" + fee + "元";
  12. }else
  13. {
  14. //其他人一律不同意
  15. str = "失败:项目经理不同意【" + user + "】的聚餐费用,金额为" + fee + "元";
  16. }
  17. }else
  18. {
  19. //超过500,继续传递给级别更高的人处理
  20. if(getSuccessor() != null)
  21. {
  22. return getSuccessor().handleFeeRequest(user, fee);
  23. }
  24. }
  25. return str;
  26. }
  27. }
  1. public class DeptManager extends Handler {
  2. @Override
  3. public String handleFeeRequest(String user, double fee) {
  4. String str = "";
  5. //部门经理的权限只能在1000以内
  6. if(fee < 1000)
  7. {
  8. //为了测试,简单点,只同意张三的请求
  9. if("张三".equals(user))
  10. {
  11. str = "成功:部门经理同意【" + user + "】的聚餐费用,金额为" + fee + "元";
  12. }else
  13. {
  14. //其他人一律不同意
  15. str = "失败:部门经理不同意【" + user + "】的聚餐费用,金额为" + fee + "元";
  16. }
  17. }else
  18. {
  19. //超过1000,继续传递给级别更高的人处理
  20. if(getSuccessor() != null)
  21. {
  22. return getSuccessor().handleFeeRequest(user, fee);
  23. }
  24. }
  25. return str;
  26. }
  27. }
  1. public class GeneralManager extends Handler {
  2. @Override
  3. public String handleFeeRequest(String user, double fee) {
  4. String str = "";
  5. //总经理的权限很大,只要请求到了这里,他都可以处理
  6. if(fee >= 1000)
  7. {
  8. //为了测试,简单点,只同意张三的请求
  9. if("张三".equals(user))
  10. {
  11. str = "成功:总经理同意【" + user + "】的聚餐费用,金额为" + fee + "元";
  12. }else
  13. {
  14. //其他人一律不同意
  15. str = "失败:总经理不同意【" + user + "】的聚餐费用,金额为" + fee + "元";
  16. }
  17. }else
  18. {
  19. //如果还有后继的处理对象,继续传递
  20. if(getSuccessor() != null)
  21. {
  22. return getSuccessor().handleFeeRequest(user, fee);
  23. }
  24. }
  25. return str;
  26. }
  27. }

客户端类

  1. public class Client {
  2. public static void main(String[] args) {
  3. //先要组装责任链
  4. Handler h1 = new GeneralManager();
  5. Handler h2 = new DeptManager();
  6. Handler h3 = new ProjectManager();
  7. h3.setSuccessor(h2);
  8. h2.setSuccessor(h1);
  9. //开始测试
  10. String test1 = h3.handleFeeRequest("张三", 300);
  11. System.out.println("test1 = " + test1);
  12. String test2 = h3.handleFeeRequest("李四", 300);
  13. System.out.println("test2 = " + test2);
  14. System.out.println("---------------------------------------");
  15. String test3 = h3.handleFeeRequest("张三", 700);
  16. System.out.println("test3 = " + test3);
  17. String test4 = h3.handleFeeRequest("李四", 700);
  18. System.out.println("test4 = " + test4);
  19. System.out.println("---------------------------------------");
  20. String test5 = h3.handleFeeRequest("张三", 1500);
  21. System.out.println("test5 = " + test5);
  22. String test6 = h3.handleFeeRequest("李四", 1500);
  23. System.out.println("test6 = " + test6);
  24. }
  25. }
职责链灵活在哪
1. 改变内部的传递规则
在内部,项目经理完全可以跳过人事部到那一关直接找到总经理。
每个人都可以去动态地指定他的继任者。
2. 可以从职责链任何一关开始。
如果项目经理不在,可以直接去找部门经理,责任链还会继续,没有影响。
3.用与不用的区别
不用职责链的结构,我们需要和公司中的每一个层级都发生耦合关系。
如果反映在代码上即使我们需要在一个类中去写上很多丑陋的if….else语句。
如果用了职责链,相当于我们面对的是一个黑箱,我们只需要认识其中的一个部门,然后让黑箱内部去负责传递就好了
 
纯的与不纯的责任链模式
一个纯的责任链模式要求一个具体的处理者对象只能在两个行为中选择一个:一是承担责任,而是把责任推给下家。不允许出现某一个具体处理者对象在承担了一部分责任后又 把责任向下传的情况。
在一个纯的责任链模式里面,一个请求必须被某一个处理者对象所接收;在一个不纯的责任链模式里面,一个请求可以最终不被任何接收端对象所接收。
纯的责任链模式的实际例子很难找到,一般看到的例子均是不纯的责任链模式的实现。
 
更多设计模式:23种设计模式系列
 

作者:jason0539

博客:http://blog.csdn.net/jason0539(转载请说明出处)

Java设计模式之责任链模式、职责链模式的更多相关文章

  1. 设计模式之第13章-职责链模式(Java实现)

    设计模式之第13章-职责链模式(Java实现) “请假都那么麻烦,至于么.”“咋的了?”“这不快过年了么,所以我想早两天回去,准备一下,买买东西什么的,然后去给项目经理请假,但是他说快过年了,所以这个 ...

  2. 责任链模式 职责链模式 Chain of Responsibility Pattern 行为型 设计模式(十七)

    责任链模式(Chain of Responsibility Pattern) 职责链模式 意图 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系 将这些对象连接成一条链,并沿着这 ...

  3. C#设计模式学习笔记:(20)职责链模式

    本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/8109100.html,记录一下学习过程以备后续查用. 一.引言 今天我们要讲行为型设计模式的第八个模式--职 ...

  4. Java设计模式(7)装饰模式(Decorator模式)

    Decorator常被翻译成"装饰",我觉得翻译成"油漆工"更形象点,油漆工(decorator)是用来刷油漆的,那么被刷油漆的对象我们称decoratee.这 ...

  5. 深入探索Java设计模式(三)之装饰器模式

    装饰器模式使你可以在运行时使用类似于对象组成的技术来装饰类.这在我们希望实例化具有新职责的对象而无需对基础类进行任何代码更改的情况下尤其有用.本文是在学习完优锐课JAVA架构VIP课程—[框架源码专题 ...

  6. Java设计模式(20)观察者模式(Observer模式)

    Java深入到一定程度,就不可避免的碰到设计模式(design pattern)这一概念,了解设计模式,将使自己对java中的接口或抽象类应用有更深的理解.设计模式在java的中型系统中应用广泛,遵循 ...

  7. Java设计模式(9)适配器模式(Adapter模式)

    适配器模式定义:将两个不兼容的类纠合在一起使用,属于结构型模式,需要有Adaptee(被适配者)和Adaptor(适配器)两个身份. 为何使用适配器模式 我们经常碰到要将两个没有关系的类组合在一起使用 ...

  8. Java 设计模式系列(八)装饰者模式

    Java 设计模式系列(八)装饰者模式 装饰模式又名包装(Wrapper)模式.装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案.Decorator 或 Wrapper 一.装饰模 ...

  9. Java 设计模式系列(十二)策略模式(Strategy)

    Java 设计模式系列(十二)策略模式(Strategy) 策略模式属于对象的行为模式.其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换.策略模式使得算法可以 ...

  10. Java 设计模式系列(十四)命令模式(Command)

    Java 设计模式系列(十四)命令模式(Command) 命令模式把一个请求或者操作封装到一个对象中.命令模式允许系统使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复 ...

随机推荐

  1. Parallel类

    Parallel类是对线程很好的一个抽象.该类位于System.Threading.Tasks名称空间中,提供了数据和任务并行性. Parallel类定义了并行的for和foreach的静态方法.Pa ...

  2. 数据库路由中间件MyCat - 源代码篇(6)

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 3. 连接模块 3.3 AbstractConnection: 3.3.2 NIOHandler NIOHa ...

  3. httpd.conf------Apache主站点配置

    Apache主站点配置 Apache的配置由httpd.conf文件配置,因此下面的配置指令都是在httpd.conf文件中修改. Apache主站点基本配置:ServerRoot “/mnt/sof ...

  4. Solr 6.7学习笔记(04)-- Suggest

    当我们使用baidu或者Google时,你输入很少的字符,就会自动跳出来一些建议选项,在Solr里,我们称之为Suggest,在solrconfig.xml里做一些简单的配置,即可实现这一功能.配置如 ...

  5. Jmeter接口自动化参数化 (转自软件测试部落)

    测试场景: 有个查询城市(大概一百个 )天气预报的接口(需求参考第一课),需要根据不同的citycode,去查询对应城市的天气预报,这种接口该如何去测试呢? 分析需求: 不管是功能测试需求,还是接口测 ...

  6. hdu 6155 - Subsequence Count

    话说这题比赛时候过的好少,连题都没读TOT 先考虑dp求01串的不同子序列的个数. dp[i][j]表示用前i个字符组成的以j为结尾的01串个数. 如果第i个字符为0,则dp[i][0] = dp[i ...

  7. js实现考试随机选题

    考试的时候经常用到,发在这里记录一下 基本信息包括: 学号.姓名.题号.题目名称 实现原理:给每一个题目添加一个编号,JS生成随机数,遍历每一个学生,把题目根据生成的随机数作为题目编号放入学生信息中 ...

  8. Git 深度学习填坑之旅二(文件三种状态、打标签)

    0x01 三种状态 Git 有三种状态,你的文件可能处于其中之一: 已提交(committed).已修改(modified)和已暂存(staged). 已提交表示数据已经安全的保存在本地数据库中. 已 ...

  9. IOS 打包提示 No iTunes Connect access for the team

    1.可以在提示页直接点击 Manage Accounts按钮,进去页面后,选择开发者账号点减号删除:(或者在Xcode中直接按command+键进入,选择accounts,选中账号按-键删除) 2.完 ...

  10. Codeforces 183C(有向图上的环长度)

    因为公用一个系统所以大家求gcd:衡量各点之间的拓扑位置,如果到达同一点有不同的长度则取gcd. #include <cstdio> #include <cstring> #i ...