本文继续介绍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. The web.config file for this project is missing the required DirectRequestModule.

    The web.config file for this project is missing the required DirectRequestModule.   将应用程序集的模式由集成改为经典 ...

  2. LaTeX 语法

    MathJax是什么? MathJax是一个开源JavaScript库.它支持LaTeX.MathML.AsciiMath符号,可以运行于所有流行浏览器上. LaTeX是什么? LaTeX(LATEX ...

  3. MS SQL JSON类型type

    在MS SQL Server 2016,已经支持JSON处理. 执行下面代码,将获取ms sql server对象类型以及其说明: IF OBJECT_ID('tempdb.dbo.#json_typ ...

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

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 3. 连接模块 如之前所述,MyCat的连接分为前端和后端,下面是连接基本相关类图: 3.1 Closabl ...

  5. SCUT - 157 - CC和他的GCD - 容斥原理

    https://scut.online/p/157 鉴于多年(都没几个月)搞数论的经验,这种时候枚举g肯定是对的. 那么肯定是要莫比乌斯函数作为因子,因为很显然? 但是为什么要搞个负的呢?其实是因为这 ...

  6. 洛谷U3348 A2-回文数

    U3348 A2-回文数 题目背景 方方方很喜欢回文数,于是就有了一道关于回文数的题目. 题目描述 求从小到大第n(1<=n<=10^18)个回文数. 注释:出题人认为回文数不包括0. 输 ...

  7. 剑指Offer的学习笔记(C#篇)-- 树的子结构

    题目描述 输入两棵二叉树A,B,判断B是不是A的子结构.(ps:我们约定空树不是任意一个树的子结构) 一 . 二叉树的概念         树形结构是一种典型的非线性结构,除了用于表示相邻关系外,还可 ...

  8. 聊聊ES6中的generator

    generatorgenerator(生成器)是ES6标准引入的新的数据类型.一个generator看上去像一个函数,但函数执行中间可以停止. ES6定义generator标准的哥们借鉴了Python ...

  9. 深入理解JVM的类加载

    前言: 前面又说到Java程序实际上是将.class文件放入JVM中运行.虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验,转换,解析和初始化,最终形成可以被虚拟机直接使用的Java类 ...

  10. [LOJ 2190] 「SHOI2014」信号增幅仪

    [LOJ 2190] 「SHOI2014」信号增幅仪 链接 链接 题解 坐标系直到 \(x\) 轴与椭圆长轴平行 点的坐标变换用旋转公式就可以了 因为是椭圆,所以所有点横坐标除以 \(p\) 然后最小 ...