1.职责链模式讲解

1.1职责链定义

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

1.2职责链模式的要点

动态的构建流程步骤,这样随时都可以重新组合出线的流程。

对于请求者而言,并不知道最终的接受者是谁,但是一般情况下,总会有一个对象来处理,称为隐式接受者。

在标准的职责链模式中,只有对象处理了该请求,这个请求就到此为止,不会再被传递了。

1.3职责链模式的结构和说明




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


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

1.4职责链模式示例代码

package demo22.chainofresponsibility.example2;
/**
* 职责的接口,也就是处理请求的接口
*/
public abstract class Handler {
/**
* 持有后继的职责对象
*/
protected Handler successor;
/**
* 设置后继的职责对象
* @param successor 后继的职责对象
*/
public void setSuccessor(Handler successor) {
this.successor = successor;
}
/**
* 示意处理请求的方法,虽然这个示意方法是没有传入参数,
* 但实际是可以传入参数的,根据具体需要来选择是否传递参数
*/
public abstract void handleRequest();
}
************************************************************************
package demo22.chainofresponsibility.example2;
/**
* 具体的职责对象,用来处理请求
*/
public class ConcreteHandler1 extends Handler {
public void handleRequest() {
//根据某些条件来判断是否属于自己处理的职责范围
//判断条件比如:从外部传入的参数,或者这里主动去获取的外部数据,
//如从数据库中获取等,下面这句话只是个示意
boolean someCondition = false; if(someCondition){
//如果属于自己处理的职责范围,就在这里处理请求
//具体的处理代码
System.out.println("ConcreteHandler1 handle request");
}else{
//如果不属于自己处理的职责范围,那就判断是否还有后继的职责对象
//如果有,就转发请求给后继的职责对象
//如果没有,什么都不做,自然结束
if(this.successor!=null){
this.successor.handleRequest();
}
}
}
}
**********************************************************************
package demo22.chainofresponsibility.example2;
/**
* 具体的职责对象,用来处理请求
*/
public class ConcreteHandler2 extends Handler {
public void handleRequest() {
//根据某些条件来判断是否属于自己处理的职责范围
//判断条件比如:从外部传入的参数,或者这里主动去获取的外部数据,
//如从数据库中获取等,下面这句话只是个示意
boolean someCondition = true; if(someCondition){
//如果属于自己处理的职责范围,就在这里处理请求 //具体的处理代码
System.out.println("ConcreteHandler2 handle request");
}else{
//如果不属于自己处理的职责范围,那就判断是否还有后继的职责对象
//如果有,就转发请求给后继的职责对象
//如果没有,什么都不做,自然结束
if(this.successor!=null){
this.successor.handleRequest();
}
}
}
}
**********************************************************************
package demo22.chainofresponsibility.example2;
/**
* 职责链的客户端,这里只是个示意
*/
public class Client {
public static void main(String[] args) {
// 先要组装职责链
Handler h1 = new ConcreteHandler1();
Handler h2 = new ConcreteHandler2(); h1.setSuccessor(h2);
// 然后提交请求
h1.handleRequest();
}
}

1.5职责链模式的本质

分离职责,动态组合

1.6职责链模式的优缺点

优点:

请求者和接收者松散耦合

动态组合职责


缺点:

产生很多细粒化对象

不一定被处理

1.7何时选用

如果多个对象可以处理同一个请求,但是具体由哪个对象来处理该请求,是运行时刻动态确定的。

在不明确指定接受者的情况下,向多个对象中的一个提交请求的话,可以用职责链模式。

如果想动态指定处理一个请求的对象集合,也可以使用职责链模式。

2.职责链模式案例分析

1.案例分析一

java中最明显的一个责任链模式的案例就是异常的抛出,大家可以仔细看看java的类库

来考虑这样一个功能:申请聚餐费用的管理。

很多公司都是这样的福利,就是项目组或者是部门可以向公司申请一些聚餐费用,用于组织项目组成员或者是部门成员进行聚餐活动。

申请聚餐费用的大致流程一般是:由申请人先填写申请单,然后交给领导审批,如果申请批准下来,领导会通知申请人审批通过,然后申请人去财务领取费用,如果没有批准下来,领导会通知申请人审批未通过,此事也就此作罢。

不同级别的领导,对于审批的额度是不一样的,比如,项目经理只能审批500元以内的申请;部门经理能审批1000元以内的申请;而总经理可以审核任意额度的申请。

也就是说,当某人提出聚餐费用申请的请求后,该请求会经由项目经理、部门经理、总经理之中的某一位领导来进行相应的处理,但是提出申请的人并不知道最终会由谁来处理他的请求,一般申请人是把自己的申请提交给项目经理,或许最后是由总经理来处理他的请求。

可以使用责任链模式来实现上述功能:当某人提出聚餐费用申请的请求后,该请求会在 项目经理—〉部门经理—〉总经理 这样一条领导处理链上进行传递,发出请求的人并不知道谁会来处理他的请求,每个领导会根据自己的职责范围,来判断是处理请求还是把请求交给更高级别的领导,只要有领导处理了,传递就结束了。

需要把每位领导的处理独立出来,实现成单独的职责处理对象,然后为它们提供一个公共的、抽象的父职责对象,这样就可以在客户端来动态地组合职责链,实现不同的功能要求了。

结构图如下

 

范例代码如下

package demo22.chainofresponsibility.example3;
/**
* 定义职责对象的接口
*/
public abstract class Handler {
/**
* 持有下一个处理请求的对象
*/
protected Handler successor = null;
/**
* 设置下一个处理请求的对象
* @param successor 下一个处理请求的对象
*/
public void setSuccessor(Handler successor){
this.successor = successor;
}
/**
* 处理聚餐费用的申请
* @param user 申请人
* @param fee 申请的钱数
* @return 成功或失败的具体通知
*/
public abstract String handleFeeRequest(String user,double fee);
}
***************************************************************************************************
package demo22.chainofresponsibility.example3;
public class DepManager extends Handler{ public String handleFeeRequest(String user, double fee) {
String str = "";
//部门经理的权限只能在1000以内
if(fee < 1000){
//为了测试,简单点,只同意小李申请的
if("小李".equals(user)){
str = "部门经理同意"+user+"聚餐费用"+fee+"元的请求";
}else{
//其他人一律不同意
str = "部门经理不同意"+user+"聚餐费用"+fee+"元的请求";
}
return str;
}else{
//超过1000,继续传递给级别更高的人处理
if(this.successor!=null){
return this.successor.handleFeeRequest(user, fee);
}
}
return str;
}
}
**************************************************************************************************
package demo22.chainofresponsibility.example3;
public class ProjectManager extends Handler{ public String handleFeeRequest(String user, double fee) {
String str = "";
//项目经理的权限比较小,只能在500以内
if(fee < 500){
//为了测试,简单点,只同意小李的
if("小李".equals(user)){
str = "项目经理同意"+user+"聚餐费用"+fee+"元的请求";
}else{
//其他人一律不同意
str = "项目经理不同意"+user+"聚餐费用"+fee+"元的请求";
}
return str;
}else{
//超过500,继续传递给级别更高的人处理
if(this.successor!=null){
return successor.handleFeeRequest(user, fee);
}
}
return str;
}
}
**************************************************************************************************
package demo22.chainofresponsibility.example3;
public class GeneralManager extends Handler{
public String handleFeeRequest(String user, double fee) {
String str = "";
//总经理的权限很大,只要请求到了这里,他都可以处理
if(fee >= 1000){
//为了测试,简单点,只同意小李的
if("小李".equals(user)){
str = "总经理同意"+user+"聚餐费用"+fee+"元的请求";
}else{
//其他人一律不同意
str = "总经理不同意"+user+"聚餐费用"+fee+"元的请求";
}
return str;
}else{
//如果还有后继的处理对象,继续传递
if(this.successor!=null){
return successor.handleFeeRequest(user, fee);
}
}
return str;
}
}
**************************************************************************************************
package demo22.chainofresponsibility.example3;
public class Client {
public static void main(String[] args) {
// 先要组装职责链
Handler h1 = new GeneralManager();
Handler h2 = new DepManager();
Handler h3 = new ProjectManager();
h3.setSuccessor(h2);
h2.setSuccessor(h1); // 开始测试
String ret1 = h3.handleFeeRequest("小李", 300);
System.out.println("the ret1=" + ret1);
String ret2 = h3.handleFeeRequest("小张", 300);
System.out.println("the ret2=" + ret2); String ret3 = h3.handleFeeRequest("小李", 600);
System.out.println("the ret3=" + ret3);
String ret4 = h3.handleFeeRequest("小张", 600);
System.out.println("the ret4=" + ret4); String ret5 = h3.handleFeeRequest("小李", 1200);
System.out.println("the ret5=" + ret5);
String ret6 = h3.handleFeeRequest("小张", 1200);
System.out.println("the ret6=" + ret6);
}
}

2.案例分析二(通用的请求处理方式)

如果我们现在要申请一个其他消费的什么业务,那么我们就需要修改接口,增加方法才行,很显然,这样做是不符合设计模式的设计原则的。下面来介绍一种通用的请求处理方式。其实很简单,我们定义一个通用的业务方法,这个业务方法不区分具体的业务,那么如何区分具体的业务呢?我们可以在通用的请求对象中,添加一个业务的标记,到了职责连对象中,愿意处理,就和原来使用一样的处理方式,如果不愿意处理,就传递到下一个业务对象就可以了。代码就不贴了,思想理解就好。
参考链接:http://www.cnblogs.com/kym/archive/2009/04/06/1430078.html

http://www.cnblogs.com/java-my-life/archive/2012/05/28/2516865.html

设计模式24---设计模式之职责链模式(Chain of Responsibility)(行为型)的更多相关文章

  1. atitit.设计模式(1)--—职责链模式(chain of responsibility)最佳实践O7 日期转换

    atitit.设计模式(1)---职责链模式(chain of responsibility)最佳实践O7 日期转换 1. 需求:::日期转换 1 2. 可以选择的模式: 表格模式,责任链模式 1 3 ...

  2. 重温设计模式(三)——职责链模式(chain of responsibility)

    一. 写在前面的 这么多的设计模式,我觉得职责链是我第一次看上去最简单,可是回想起来却又最复杂的一个模式. 因此,这个文章我酝酿了很久,一直也没有胆量发出来,例子也是改了又改,可是仍然觉得不够合理.所 ...

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

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

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

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

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

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

  6. 职责链模式(Chain of Responsibility)(对象行为型)

    1.概述 你去政府部门求人办事过吗?有时候你会遇到过官员踢球推责,你的问题在我这里能解决就解决,不能解决就推卸给另外个一个部门(对象).至于到底谁来解决这个问题呢?政府部门就是为了可以避免屁民的请求与 ...

  7. 责任链模式/chain of responsibility/行为型模式

    职责链模式 chain of responsibility 意图 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处 ...

  8. 设计模式的征途—14.职责链(Chain of Responsibility)模式

    相信大家都玩过类似于“斗地主”的纸牌游戏,某人出牌给他的下家,下家看看手中的牌,如果要不起,则将出牌请求转发给他的下家,其下家再进行判断.一个循环下来,如果其他人都要不起该牌,则最初的出牌者可以打出新 ...

  9. 设计模式之职责链模式(Chain of Responsibility)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

  10. 设计模式:职责链模式(Chain of Responsibility)

    去年参加校招要到长沙来,这个对于我来说不是特别喜欢(但又必须的来,谁叫咱不是985.211的娃呢),但是对于某些人来说就是福音了.大四还有课,而且学校抓的比较严,所以对于那些想翘课的人来说这个是最好不 ...

随机推荐

  1. Linux使用问答

    1.ubuntu 查看安装的软件包? 在终端输入 sudo dpkg -l http://vardesa.blog.hexun.com/58593247_d.html 其他:http://qiuye. ...

  2. Highcharts 本地导出图片和PDF asp.net mvc版

    啰嗦: 现在大家利用Highcharts开发时,有时候会遇到导出的功能问题,但是highcharts默认是链接自己的服务器上进行处理,但是有时候我们会连不上他的服务器,所以我们要让他在我们的服务器上进 ...

  3. JVM 找出最耗 cpu的线程 并打印线程栈

    监控JVM中最占cpu的线程 top -Hp pid JVM中最占cpu的线程ID -o THREAD,tid,time | awk 'BEGIN {count=0; } { if($2>0.3 ...

  4. Ogre实现简单地形

    利用SimpleRenderable实现DirectX 9 3D 游戏设计入门中 第十三章 地形渲染基础的简单地形,只是简单的实现了地形的基本框架,顶点,索引,纹理等,为简单起见高度都为1,适合新手做 ...

  5. Linq 筛选出一条数据

    InBoxInfo boxInfo = boxList.Find(p => p.GoodsID == goods.GoodsID.ToString().Trim() && p.S ...

  6. Ubuntu 安装基础教程

    转自:http://teliute.org/linux/Ubsetup/index.html 1.进入 live cd 桌面  1)设置好启动后,断开网络,然后重启动计算机,可以用硬盘启动,也可以刻成 ...

  7. 循环冗余校验(CRC)算法入门引导

    目录 写给嵌入式程序员的循环冗余校验CRC算法入门引导 前言 从奇偶校验说起 累加和校验 初识 CRC 算法 CRC算法的编程实现 前言 CRC校验(循环冗余校验)是数据通讯中最常采用的校验方式.在嵌 ...

  8. PHP数组和Json之间的互相转换 json_encode() 和 json_decode()

    之所以要用到Json,很多时候是因为使用ajax对象时,程序与JS函数之间的数据交互.因为JS不认识PHP中的数组,PHP也不认识JS中的数组或对象.Json很好的解决了这个问题. Json简介 JS ...

  9. 【CF】207 Div.1 B.Xenia and Hamming

    这题目一看很牛逼,其实非常easy.求求最小公倍数,最大公约数,均摊复杂度其实就是O(n). /* 356B */ #include <iostream> #include <str ...

  10. 能让你成为更优秀程序员的10个C语言资源

    能让你成为更优秀程序员的10个C语言资源 本文由 伯乐在线 - archychu 翻译自 mycplus.欢迎加入 技术翻译小组.转载请参见文章末尾处的要求. 一些人觉得编程无聊,一些人觉得它很好玩. ...