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. EntityFramework动态组合多排序字段

    前言:在使用EF当中,肯定会遇到动态查询的需求,建立一个公共调用的动态组合表达式查询也是必不可少的,以下是建立动态组合多排序字段做个记录,供以后调用 1.建立一个结构,用于多个排序字段组合,这个结构体 ...

  2. slivelight5和数据库交互

    最近开始研究sliverlight和数据库交互了,无奈网上资料较少,查阅了大量资料终于成功了,但是我记得还有别的方法,希望大家讨论一下 数据访问层我的用的是ado.net实体数据模型 然后新建了一个w ...

  3. LightOj_1321 Sending Packets

    题目链接 题意: 给一个数据大小为S的数据包, 每一次发送需要K秒(单向),现在要从节点0 发送到节点 n-1. 其中有n - 1条路径, 每条路径都有一个传输成功率. 问传输成功所需最小时间的期望. ...

  4. leetcode第八题 String to Integer (atoi) (java)

    String to Integer (atoi) time=272ms   accepted 需考虑各种可能出现的情况 public class Solution { public int atoi( ...

  5. capitalize()在Python中含义

    Python为string对象提供了转换大小写的方法:upper() 和 lower(). 还不止这些,Python还为我们提供了首字母大写,其余小写的capitalize()方法, 以及所有单词首字 ...

  6. HttpWebRequest提高效率之连接数,代理,自动跳转,gzip请求等设置问题

    先设置4个: [csharp] webrequest.ServicePoint.Expect100Continue = false; //是否使用 Nagle 不使用 提高效率 webrequest. ...

  7. VMware配置回环地址用于测试

           我们在开发过程中,很可能需要一台服务器用于测试,在这种环境下,我们很可能需要用到vmware来构建这样的开发环境.但如果当前处在一个离线,或是不在网内的环境下,我们所搭建的环境有可能无法 ...

  8. 如何用Python从本地将一个文件备份到Google Drive

    1.要有一个Google App账号: 这个可以上网上去申请,申请地址为:https://developers.google.com/appengine/?hl=zh-cn 2.创建一个Google ...

  9. 17.1.1.7 Setting Up Replication with New Master and Slaves 设置复制使用新的master和slaves:

    17.1.1.7 Setting Up Replication with New Master and Slaves 设置复制使用新的master和slaves: 最简单和最直接方式是设置复制使用新的 ...

  10. 【CF】196 Div.2 D. Book of Evil

    显然这个图是一课树,看着题目首先联想到LCA(肯定是可以解的).但是看了一下数据大小,应该会TLE.然后,忽然想到一个前面做过的题目,大概是在一定条件下树中某结点旋转成为根后查询最长路径.结果灵感就来 ...