JAVA设计模式(13):行为型-责任链模式(Responsibility)

定义

将能够处理同一类请求的对象连成一条链,所提交的请求沿着链传递,链上的对象逐个判断是否有能力处理该请求,

如果能则处理,如果不能则传递给链上的一个对象。

场景:

  • 打牌时,轮流出牌
  • 接力赛跑
  • 大学中,奖学金审批
  • 公司中,公文审批

开发中常见的场景:

  • Java中,异常机制就是一种责任链模式。一个try可以对应多个catch,当第一个catch不匹配类型,则自动跳到第二个catch。
  • Javascript语言中,事件的冒泡和捕获机制。Java语言中,事件的处理采用观察者模式。
  • Servlet开发中,过滤器的链式处理
  • Struts2中,拦截器的调用也是典型的责任链模式

职责链模式

使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系,

将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止。

角色

抽象处理者角色(Handler):定义出一个处理请求的接口。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。

具体处理者角色(ConcreteHandler):具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。

抽象处理者角色

[java] view
plain
copyprint?

  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. }

具体处理者角色

[java] view
plain
copyprint?

  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. }

客户端类

[java] view
plain
copyprint?

  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元以内的申请;而总经理可以审核任意额度的申请。

当某人提出聚餐费用申请的请求后,该请求会经由项目经理、部门经理、总经理之中的某一位领导来进行相应的处理,但是提出申请的人并不知道最终会由谁来处理他的请求,一般申请人是把自己的申请提交给项目经理,或许最后是由总经理来处理他的请求。申请人只要直接与项目经理交互就可以,其余的工作在黑盒中,究竟流程是怎样的,最后是由谁审批通过的,申请人无需关心。

抽象处理者角色类

[java] view
plain
copyprint?

  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. }

具体处理者角色

[java] view
plain
copyprint?

  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. }

[java] view
plain
copyprint?

  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. }

[java] view
plain
copyprint?

  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. }

客户端类

[java] view
plain
copyprint?

  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语句。

如果用了职责链,相当于我们面对的是一个黑箱,我们只需要认识其中的一个部门,然后让黑箱内部去负责传递就好了

纯的与不纯的责任链模式

一个纯的责任链模式要求一个具体的处理者对象只能在两个行为中选择一个:一是承担责任,而是把责任推给下家。不允许出现某一个具体处理者对象在承担了一部分责任后又 把责任向下传的情况。

在一个纯的责任链模式里面,一个请求必须被某一个处理者对象所接收;在一个不纯的责任链模式里面,一个请求可以最终不被任何接收端对象所接收。

纯的责任链模式的实际例子很难找到,一般看到的例子均是不纯的责任链模式的实现。

时间: 2024-10-11 21:34:52

JAVA设计模式(13):行为型-责任链模式(Responsibility)的相关文章

Java设计模式(九)责任链模式 命令模式

(十七)责任链模式 责任链模式的目的是通过给予多个对象处理请求的机会,已解除请求发送者与接受者之间的耦合关系.面对对象的开发力求对象之前保持松散耦合,确保对象各自的责任最小化,这样的设计可以使得系统更加容易修改,同时降低产生缺陷的风险. public class ChainTest { public static void main(String[] args) { String pass1="123456"; String pass2="123456"; Stri

java设计模式(五)责任链模式

很多对象有每个对象对其下家的引用而连接起来形成一条链,请求在这条链上传递,直到链上某个对象决定处理此请求,应用场景如单位审批流程等. 要点:1)抽象处理者角色:定义处理请求接口及设定下家引用    2)具体处理着角色:具体处理请求或选择将请求传给下家 1.抽象处理者角色类,定义处理请求接口及下家引用 public abstract class PriceHandle { protected PriceHandle successor; public void setSuccessor(Price

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

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

PHP设计模式学习笔记: 责任链模式(Chain of Responsibility)

// 抽象书本类 abstract class AbstractBookTopic { abstract function getTopic(); abstract function getTitle(); abstract function setTitle($title_in); } // 书本类,继承自抽象书本类 class BookTopic extends AbstractBookTopic { private $topic; private $title; function __co

设计模式-(15)责任链模式 (swift版)

一,概念: 责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链.这种模式给予请求的类型,对请求的发送者和接收者进行解耦.这种类型的设计模式属于行为型模式.在这种模式中,通常每个接收者都包含对另一个接收者的引用.如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推. 主要解决职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了.

java23种设计模式之十:责任链模式

最近在学习netty中发现其中用到了责任链模式,然后结合自己在写代码中遇到了大量写if...else的情况,决定学习一下责任链模式. 一.什么样的场景下会选择用责任链模式 我们在进行业务逻辑判断时,需要根据传入参数类型的不同做出不同的处理,如果在传入的参数类型相对较少的情况时,可以用if...else来做判断,这样的确是没有什么问题的,但是如果后期由于业务系统的扩展,导致参数类型会随之延伸出很多种不同的处理,这时就需要用责任链模式来抒代码重构,这样会让代码封装的更好.更简洁,阅读性更强,后期如果

浅谈Java五大设计原则之责任链模式

首先我们得先定义一个责任链模式: 责任链模式是一种线性执行流程,多个对象都有机会去执行同一个任务,只是在执行过程中, 由于执行的权利和范围不一样,那么当自己不能处理此任务时,就必须将这个任务抛给下一个对象, 一次类推,就形成了一个执行链. 典型例子就是Tomcat中的过滤器,当配置了多个过滤器时,就会形成一条过滤链,客户端发起 的请求会经过这条过滤链上的每一个过滤器,最终只有一个过滤器去处理这个请求. 纯与不纯的责任链: 1.纯的责任链是在整条链中,只有一个对象可以处理这个任务.不会处理完一半,

设计模式学习笔记之责任链模式

责任链模式 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这些对象连成一条链,并沿着这条链检查该请求,并对其进行处理,或者将它传递给下一个对象. 责任链模式有两个角色组成: 抽象处理者角色:它定义了一个处理请求的接口.当然对于链子的不同实现,也可以在这个角色中实现后继链. 具体处理者角色:实现抽象处理者定义的接口,并处理它所负责的请求. 下面是<设计模式>中给出的适用范围:    1) 有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定.    2)

大话设计模式读书笔记--19.责任链模式

定义 责任链模式定义: 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系,将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它 比如: 员工小张向组长申请加薪, 组长没这个权利并将请求告诉部长,部长同意了小张的加薪请求 模式结构 代码实现 场景: 经理可以批准请假, 经理的上级是总监, 总监可以批准加薪 代码实现:点击下载 优点 1.客户端不知道哪一个对象最终处理请求,在不影响客户端的情况下可以动态的重新组织和分配责任 2.链中的对象并不知道链的结构,只需保持