职责链模式 Responsibility of Chain

在职责链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织链和分配责任。

职责链模式的意图

        使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。[当然也有可能不被任何对象处理]

职责链模式的结构

参与者

  • Handler——定义一个处理请求的接口。如果需要,接口可以定义一个方法,以设定和返回对下家的引用。这个角色通常由一个JAVA抽象类或者JAVA接口实现。其示意性类图如下图所示。图中的聚合关系给出了具体子类对下家的引用,抽象方法handleRequest()规范了子类处理请求的操作。



  • ConcreteHandler——处理它所负责的请求。
                              ——可访问它的后继者
                              ——如果可处理该请求,就处理;否则将该请求转发给它的后继者
  • Client——向链上的具体处理者对象提交请求

协作

当客户提交一个请求时,请求沿链传递直至有一个ConcreteHandler 对象负责处理它。

使用场景

职责链可能是一条直线、一个环链或者一个树结构的一部分。为了方便,我们使用一个简单的例子。公司人事的请假流程:请假一天组长批了即可、两到三天项目经理批了即可、三天以上需总经理批准。我们来看看源码实现:

//抽象处理角色:

  1. package headfirst.ChainOfResponsibility;
  2.  
  3. /**
  4. * @author Nick Lau
  5. * 抽象处理角色
  6. */
  7. public abstract class Handler {
  8. //持有处理请求的对象
  9. protected Handler successor = null;
  10.  
  11. //取得后继者
  12. public Handler getSuccessor() {
  13. return successor;
  14. }
  15.  
  16. //设置下一个处理请求的对象
  17. public void setSuccessor(Handler successor) {
  18. this.successor = successor;
  19. }
  20.  
  21. /**
  22. * @param role 角色
  23. * @param days 请假天数
  24. * @return 审批成功或失败后返回的提示
  25. */
  26. public abstract String handleRequest(String role, int days);
  27. }

下面是具体处理者的示意性源码。显然,处理者的逻辑非常简单,如果一个具体处理者有下家,就将请求传递给下家;如果没有下家,就处理掉。

  1. package headfirst.ChainOfResponsibility;
  2.  
  3. /**
  4. * @author Nick Lau
  5. * TeamLeader处理请假事项
  6. */
  7. public class TeamLeader extends Handler {
  8.  
  9. @Override
  10. public String handleRequest(String role, int days) {
  11. // TODO Auto-generated method stub
  12. String tips = "";
  13. if (days == 1) {
  14. if ("TeamLeader".equals(role)) {
  15. tips = "TeamLeader agree " + days + " day(s) leave.";
  16. } else {
  17. tips = "请假1天TeamLeader批准即可。";
  18. }
  19. } else {//传递给下一个继承者处理
  20. if (getSuccessor() != null)
  21. return getSuccessor().handleRequest(role, days);
  22. }
  23. return tips;
  24. }
  25.  
  26. }
  1. package headfirst.ChainOfResponsibility;
  2.  
  3. public class ProjectManager extends Handler {
  4.  
  5. @Override
  6. public String handleRequest(String role, int days) {
  7. // TODO Auto-generated method stub
  8. String tips = "";
  9. if (days > 1 && days <=3) {
  10. if ("ProjectManager".equals(role)) {
  11. tips = "ProjectManager agree " + days + " day(s) leave.";
  12. } else {
  13. tips = "请假1天TeamLeader批准即可;4天以上需总经理批准!";
  14. }
  15. } else {//如果还有下一个处理者则传递给下一个继承者处理
  16. if (getSuccessor() != null)
  17. return getSuccessor().handleRequest(role, days);
  18. }
  19. return tips;
  20. }
  21.  
  22. }
  1. package headfirst.ChainOfResponsibility;
  2.  
  3. public class GeneralManager extends Handler{
  4.  
  5. @Override
  6. public String handleRequest(String role, int days) {
  7. // TODO Auto-generated method stub
  8. String tips = "";
  9. if (days > 3) {
  10. if ("GeneralManager".equals(role)) {
  11. tips = "GeneralManager agree " + days + " day(s) leave.";
  12. } else {
  13. tips = role + "无权限处理" + days + "天请假事宜。";
  14. }
  15. } else {//传递给下一个继承者处理
  16. if (getSuccessor() != null)
  17. return getSuccessor().handleRequest(role, days);
  18. }
  19. return tips;
  20. }
  21.  
  22. }

当然,在大多数情况下,这么简单的处理逻辑是没有实际用途的。真实的处理逻辑和所研究的系统商业逻辑密切相关,这里使用最简化的商业逻辑,有助于我们将精力集中到如何将模式应用到设计中去。

客户端的源码清单如下:

  1. package headfirst.ChainOfResponsibility;
  2.  
  3. public class Client {
  4.  
  5. /**
  6. * @param args
  7. */
  8. public static void main(String[] args) {
  9. // TODO Auto-generated method stub
  10. Handler teamLeader = new TeamLeader();
  11. Handler projectManager = new ProjectManager();
  12. Handler generalManager = new GeneralManager();
  13. teamLeader.setSuccessor(projectManager);
  14. projectManager.setSuccessor(generalManager);
  15.  
  16. String test1 = teamLeader.handleRequest("TeamLeader", 1);
  17. System.out.println(test1);
  18. String test2 = teamLeader.handleRequest("ProjectManager", 1);
  19. System.out.println(test2);
  20. System.out.print("+++++++++++++++++++++++++++++++++++++++++++++++++\n");
  21.  
  22. String test3 = teamLeader.handleRequest("ProjectManager", 3);
  23. System.out.println(test3);
  24. String test4 = teamLeader.handleRequest("GeneralManager", 3);
  25. System.out.println(test4);
  26. System.out.print("+++++++++++++++++++++++++++++++++++++++++++++++++\n");
  27.  
  28. String test5 = teamLeader.handleRequest("ProjectManager", 11);
  29. System.out.println(test5);
  30. String test6 = teamLeader.handleRequest("GeneralManager", 11);
  31. System.out.println(test6);
  32. System.out.print("+++++++++++++++++++++++++++++++++++++++++++++++++\n");
  33. }
  34.  
  35. }

客户端输出如下:

  1. TeamLeader agree 1 day(s) leave.
  2. 请假1TeamLeader批准即可。
  3. +++++++++++++++++++++++++++++++++++++++++++++++++
  4. ProjectManager agree 3 day(s) leave.
  5. 请假1TeamLeader批准即可;4天以上需总经理批准!
  6. +++++++++++++++++++++++++++++++++++++++++++++++++
  7. ProjectManager无权限处理11天请假事宜。
  8. GeneralManager agree 11 day(s) leave.
  9. +++++++++++++++++++++++++++++++++++++++++++++++++

效果

职责链模式降低了请求的发送端和接收端之间的耦合,使多个对象都有机会处理这个请求。一个链可以是一条线、一棵树、也可以是一个环。链的拓扑结构可以是单连通的或多连通的,职责链模式并不指定职责链的拓扑结构。但是职责链模式要求在同一个时间里,命令只可以被传给一个下家(或被处理掉)而不能传给多个下家。

下面情况可以使用职责链模式:

  1. 系统已经有一个由处理者对象组成的链。这个链可能由合成模式给出。
  2. 有多于一个的处理者对象会处理一个请求,而事先并不知道到底由哪一个处理者对象处理该请求。这个处理者对象是动态确定的。
  3. 系统想发出一个请求给多个处理者对象中的某一个,但是不明显指定是哪一个处理者对象。
  4. 处理一个请求的处理者对象集合需要动态地被指定。

OOP设计模式[JAVA]——03职责链模式的更多相关文章

  1. Java设计模式之《职责链模式》及应用场景

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6530089.html 职责链模式(称责任链模式)将请求的处理对象像一条长链一般组合起来,形 ...

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

     设计模式(十二)职责链模式(Chain of Responsibility)(对象行为型) 1.概述 你去政府部门求人办事过吗?有时候你会遇到过官员踢球推责,你的问题在我这里能解决就解决,不能解决就 ...

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

     设计模式(十二)职责链模式(Chain of Responsibility)(对象行为型) 1.概述 你去政府部门求人办事过吗?有时候你会遇到过官员踢球推责,你的问题在我这里能解决就解决.不能解决就 ...

  4. java 之 职责链模式(大话设计模式)

    目前很多OA办公自动化软件,加快了办公效率,简化流程.相信很多小伙伴都用过.笔者了解到的大多数办公软件底层实现流程大多数采用的都是Activity或者是JBPM框架. 今天笔者要说的也是类似于流程的一 ...

  5. java设计模式-----18、职责链模式

    概念: Chain of Responsibility(CoR)模式也叫职责链模式.责任链模式或者职责连锁模式,是行为模式之一,该模式构造一系列分别担当不同的职责的类的对象来共同完成一个任务,这些类的 ...

  6. JAVA设计模式之【职责链模式】

    职责链模式 专门处理请求链式传递的模式 角色 Handler抽象处理者 ConcreteHandler具体处理者 在职责链模式中,很多对象由每一个对象对其下家的引用而连接成一条链,请求在这条链上传递, ...

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

    职责链模式(Chain Of Responsibility):使多个对象都有机会处理请求,从而避免发送者和接收者的耦合关系.将对象连成链并沿着这条链传递请求直到被处理 下面是一个设计模式的demo: ...

  8. C#设计模式系列:职责链模式(Chain of Responsibility)

    1.职责链模式简介 1.1>.定义 职责链模式是一种行为模式,为解除请求的发送者和接收者之间的耦合,而使多个对象都有机会处理这个请求.将这些对象连接成一条链,并沿着这条链传递该请求,直到有一个对 ...

  9. 设计模式入门之职责链模式Chain Of Responsibility

    //职责链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止. //实例:申请费用的功能,不同金额的费 ...

随机推荐

  1. cocos2d_x 问题汇总

    1.生成so文件时,报“No rule to make target ”错误 解决方法:将.\xxx[appname]\proj.android\obj\local\armeabi\objs中的文件全 ...

  2. JAX-WS

    JAX-WS(Java API for XML Web Services)规范是一组XML web services的JAVA API,JAX-WS允许开发者可以选择RPC-oriented或者mes ...

  3. SQL知识累积

    详细介绍select的文章,展示原始数据.SQL.查询结果,以及在不同数据库下SQL应该如何写. https://en.wikipedia.org/wiki/Select_(SQL) 目录如下: Co ...

  4. <译>Selenium Python Bindings 5 - Waits

    如今,大多数的Web应用程序使用AJAX技术.当页面加载到浏览器,页面中的元素也许在不同的时间间隔内加载.这使得元素很难定位,如果在DOM中的元素没有呈现,它将抛出ElementNotVisibleE ...

  5. <译>Selenium Python Bindings 2 - Getting Started

    Simple Usage如果你已经安装了Selenium Python,你可以通过Python这样使用: #coding=gbk ''' Created on 2014年5月6日 @author: u ...

  6. 常见设计模式解析和实现(C++)FlyWeight模式

    作用:运用共享技术有效地支持大量细粒度的对象 UML结构图: 解析: Flyweight模式在大量使用一些可以被共享的对象的时候使用.比如,在QQ聊天时很多时候你懒得回复又不得不回复,一般会用一些客套 ...

  7. 从windows转向mac

    键盘问题: 按键对应表 Windows Mac ctrl command alt option 由此可推断,windows下的ctrl+c/v 变成了mac下的 command+c/v 功能对应表 删 ...

  8. C++调用matlab实例

    这段代码是C++调用matab引擎的过程,代码的目的很简单,在C++中创建一个vector数组,然后将这个vector数组单位化.写这个代码的目的是学些C++与matlab之间的数据交互,以供日后参考 ...

  9. hashtable,hashMap,vector和ArrayList

    关于vector,ArrayList,hashMap和hashtable之间的区别 vector和ArrayList:  线程方面:  vector是旧的,是线程安全的  ArrayList是java ...

  10. CentOS7 mariadb 修改编码

    CentOS7 mariadb 编码的修改: 网上看了不少的解决方案,要么是比较老的,要么是不正确,测试成功的方式,记录备查. 登录MySQL,使用SHOW VARIABLES LIKE 'chara ...