职责链模式 Responsibility of Chain

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

职责链模式的意图

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

职责链模式的结构

参与者

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



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

协作

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

使用场景

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

//抽象处理角色:

package headfirst.ChainOfResponsibility;

/**
* @author Nick Lau
* 抽象处理角色
*/
public abstract class Handler {
//持有处理请求的对象
protected Handler successor = null; //取得后继者
public Handler getSuccessor() {
return successor;
} //设置下一个处理请求的对象
public void setSuccessor(Handler successor) {
this.successor = successor;
} /**
* @param role 角色
* @param days 请假天数
* @return 审批成功或失败后返回的提示
*/
public abstract String handleRequest(String role, int days);
}

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

package headfirst.ChainOfResponsibility;

/**
* @author Nick Lau
* TeamLeader处理请假事项
*/
public class TeamLeader extends Handler { @Override
public String handleRequest(String role, int days) {
// TODO Auto-generated method stub
String tips = "";
if (days == 1) {
if ("TeamLeader".equals(role)) {
tips = "TeamLeader agree " + days + " day(s) leave.";
} else {
tips = "请假1天TeamLeader批准即可。";
}
} else {//传递给下一个继承者处理
if (getSuccessor() != null)
return getSuccessor().handleRequest(role, days);
}
return tips;
} }
package headfirst.ChainOfResponsibility;

public class ProjectManager extends Handler {

    @Override
public String handleRequest(String role, int days) {
// TODO Auto-generated method stub
String tips = "";
if (days > 1 && days <=3) {
if ("ProjectManager".equals(role)) {
tips = "ProjectManager agree " + days + " day(s) leave.";
} else {
tips = "请假1天TeamLeader批准即可;4天以上需总经理批准!";
}
} else {//如果还有下一个处理者则传递给下一个继承者处理
if (getSuccessor() != null)
return getSuccessor().handleRequest(role, days);
}
return tips;
} }
package headfirst.ChainOfResponsibility;

public class GeneralManager extends Handler{

    @Override
public String handleRequest(String role, int days) {
// TODO Auto-generated method stub
String tips = "";
if (days > 3) {
if ("GeneralManager".equals(role)) {
tips = "GeneralManager agree " + days + " day(s) leave.";
} else {
tips = role + "无权限处理" + days + "天请假事宜。";
}
} else {//传递给下一个继承者处理
if (getSuccessor() != null)
return getSuccessor().handleRequest(role, days);
}
return tips;
} }

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

客户端的源码清单如下:

package headfirst.ChainOfResponsibility;

public class Client {

    /**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Handler teamLeader = new TeamLeader();
Handler projectManager = new ProjectManager();
Handler generalManager = new GeneralManager();
teamLeader.setSuccessor(projectManager);
projectManager.setSuccessor(generalManager); String test1 = teamLeader.handleRequest("TeamLeader", 1);
System.out.println(test1);
String test2 = teamLeader.handleRequest("ProjectManager", 1);
System.out.println(test2);
System.out.print("+++++++++++++++++++++++++++++++++++++++++++++++++\n"); String test3 = teamLeader.handleRequest("ProjectManager", 3);
System.out.println(test3);
String test4 = teamLeader.handleRequest("GeneralManager", 3);
System.out.println(test4);
System.out.print("+++++++++++++++++++++++++++++++++++++++++++++++++\n"); String test5 = teamLeader.handleRequest("ProjectManager", 11);
System.out.println(test5);
String test6 = teamLeader.handleRequest("GeneralManager", 11);
System.out.println(test6);
System.out.print("+++++++++++++++++++++++++++++++++++++++++++++++++\n");
} }

客户端输出如下:

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

效果

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

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

  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. 【C#学习笔记】获得系统时间

    using System; namespace ConsoleApplication { class Program { static void Main(string[] args) { Conso ...

  2. android和ios流媒体库推荐

    1基本信息编辑 Vitamio是一款 Android 与 iOS 平台上的全能多媒体开发框架,全面支持硬件解码与 GPU 渲染.从2011年8月上线到2014年1月,Vitamio 凭借其简洁易用的 ...

  3. Mybatis学习——一对一关联表查询

    1.SQL语句建表 CREATE TABLE teacher( t_id ) ); CREATE TABLE class( c_id ), teacher_id INT ); ALTER TABLE ...

  4. 【JSP】弹出带输入框可 确认密码 对话框

    <body> <input type="submit" value="删除历史全部订单" onclick="deleteall()& ...

  5. java 访问器方法中对象引用的问题

    "注意不要编写返回引用可变对象的访问器方法".因为会破坏类的封装性,引用的内容可能会被改变,产生业务逻辑上的错误. 什么是可变对象? 先要搞清楚java中值传递和引用传递的问题,总结如下: 1.对象就 ...

  6. 利用c#反射实现实体类生成以及数据获取与赋值

    转:http://hi.baidu.com/xyd21c/item/391da2fc8fb351c10dd1c8b8 原有的实体类成员逐个赋值与获取的方法弊端: 1.每次对实体类属性进行赋值时,都要检 ...

  7. Hadoop集群中Hbase的介绍、安装、使用

    导读 HBase – Hadoop Database,是一个高可靠性.高性能.面向列.可伸缩的分布式存储系统,利用HBase技术可在廉价PC Server上搭建起大规模结构化存储集群. 一.Hbase ...

  8. java多线程学习笔记——详细

    一.线程类  1.新建状态(New):新创建了一个线程对象.        2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中, ...

  9. Libsvm的MATLAB调用和交叉验证

    今天听了一个师兄的讲课,才发现我一直在科研上特别差劲,主要表现在以下几个方面,(现在提出也为了督促自己在以后的学习工作道路上能够避免这些问题) 1.做事情总是有头无尾,致使知识点不能一次搞透,每次在用 ...

  10. AWR

    Automatic Workload Repository是10g引入的一个重要组件.在里面存贮着近期一段时间内,默认是7天,数据库活动状态的详细信息 手动得到一份AWR报告: SQL> exe ...