`
jendgh
  • 浏览: 16067 次
  • 性别: Icon_minigender_2
  • 来自: 济南
文章分类
社区版块
存档分类
最新评论

研磨设计模式 之 职责链模式(Chain of Responsibility)2——跟着cc学设计系列

阅读更多

23.2  解决方案

23.2.1  职责链模式来解决

用来解决上述问题的一个合理的解决方案,就是使用职责链模式。那么什么是职责链模式呢?

(1)职责链模式定义

 

(2)应用职责链模式来解决的思路

仔细分析上面的场景,当客户端提出一个聚餐费用的申请,后续处理这个申请的对象,项目经理、部门经理和总经理,自然的形成了一个链,从项目经理à部门经理à总经理,客户端的申请请求就在这个链中传递,直到有领导处理为止。看起来,上面的功能要求很适合采用职责链来处理这个业务。

要想让处理请求的流程可以灵活的变动,一个基本的思路,那就是动态构建流程步骤,这样随时都可以重新组合出新的流程来。而要让处理请求的对象也要很灵活,那就要让它足够简单,最好是只实现单一的功能,或者是有限的功能,这样更有利于修改和复用。

       职责链模式就很好的体现了上述的基本思路,首先职责链模式会定义一个所有处理请求的对象都要继承实现的抽象类,这样就有利于随时切换新的实现;其次每个处理请求对象只实现业务流程中的一步业务处理,这样使其变得简单;最后职责链模式会动态的来组合这些处理请求的对象,把它们按照流程动态组合起来,并要求它们依次调用,这样就动态的实现了流程。

这样一来,如果流程发生了变化,只要重新组合就好了;如果某个处理的业务功能发生了变化,一个方案是修改该处理对应的处理对象,另一个方案是直接提供一个新的实现,然后在组合流程的时候,用新的实现替换掉旧的实现就可以了。

23.2.2  模式结构和说明

职责链模式的结构如图23.1所示:

 

图23.1  职责链模式结构图

Handler

       定义职责的接口,通常在这里定义处理请求的方法,可以在这里实现后继链。

ConcreteHandler

       实现职责的类,在这个类里面,实现对在它职责范围内请求的处理,如果不处理,就继续转发请求给后继者。

Client

       职责链的客户端,向链上的具体处理者对象提交请求,让职责链负责处理。

23.2.3  职责链模式示例代码

(1)先来看看职责的接口定义,示例代码如下:

/**

 * 职责的接口,也就是处理请求的接口

 */

public abstract class Handler {

    /**

     * 持有后继的职责对象

     */

    protected Handler successor;

    /**

     * 设置后继的职责对象

     * @param successor 后继的职责对象

     */

    public void setSuccessor(Handler successor) {

       this.successor = successor;

    }

    /**

     * 示意处理请求的方法,虽然这个示意方法是没有传入参数,

     * 但实际是可以传入参数的,根据具体需要来选择是否传递参数

     */

    public abstract void handleRequest();

}

(2)接下来看看具体的职责实现对象,示例代码如下:

/**

 * 具体的职责对象,用来处理请求

 */

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();

           }

       }

    }

}

       另外一个ConcreteHandler2和上面ConcreteHandler1的示意代码几乎是一样的,因此就不去赘述了

(3)接下来看看客户端的示意,示例代码如下:

/**

 * 职责链的客户端,这里只是个示意

 */

public class Client {

    public static void main(String[] args) {

       //先要组装职责链

       Handler h1 = new ConcreteHandler1();

       Handler h2 = new ConcreteHandler2();

      

       h1.setSuccessor(h2);    

       //然后提交请求

       h1.handleRequest();

    }

}

23.2.4  使用职责链模式重写示例

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

需要把每位领导的处理独立出来,实现成单独的职责处理对象,然后为它们提供一个公共的、抽象的父职责对象,这样就可以在客户端来动态的组合职责链,实现不同的功能要求了。还是看一下示例的整体结构,会有助于对示例的理解和把握。如图23.2所示:

 

图23.2  使用职责链模式的示例程序的结构示意图

(1)定义职责的抽象类

       首先来看看定义所有职责的抽象类,也就是所有职责的外观,在这个类里面持有下一个处理请求的对象,同时还要定义业务处理方法,示例代码如下:

/**

 * 定义职责对象的接口

 */

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);

}

(2)实现各自的职责

       现在实现的处理聚餐费用流程是:申请人提出的申请交给项目经理处理,项目经理的处理权限是500元以内,超过500元,把申请转给部门经理处理,部门经理的处理权限是1000元以内,超过1000元,把申请转给总经理处理。

       分析上述流程,对请求主要有三个处理环节,把它们分别实现成为职责对象,一个对象实现一个环节的处理功能,这样就会比较简单。

先看看项目经理的处理吧,示例代码如下:

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;

    }

}

       接下来看看部门经理的处理,示例代码如下:

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;

    }

}

再看总经理的处理,示例代码如下:

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;

    }

}

(3)使用职责链

那么客户端如何使用职责链呢,最重要的就是要先构建职责链,然后才能使用。示例代码如下:

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); 

    }

}

运行结果如下:

the ret1=项目经理同意小李聚餐费用300.0元的请求

the ret2=项目经理不同意小张聚餐费用300.0元的请求

the ret3=部门经理同意小李聚餐费用600.0元的请求

the ret4=部门经理不同意小张聚餐费用600.0元的请求

the ret5=总经理同意小李聚餐费用1200.0元的请求

the ret6=总经理不同意小张聚餐费用1200.0元的请求

       看起来结果跟前面不用模式的实现方案的运行结果是一样的,它们本来就是实现的同样的功能,只不过实现方式不同而已。

(4)如何运行的

       理解了示例的整体结构和具体实现,那么示例的具体运行过程是怎样的呢?

下面就以“小李申请聚餐费用1200元”这个费用申请为例来说明,调用过程的示意图如图23.3所示:

 

图23.3  职责链示例调用过程示意图

 


---------------------------------------------------------------------------

私塾在线学习网原创内容  跟着cc学设计系列 之 研磨设计模式

研磨设计讨论群【252780326】

原创内容,转载请注明出处【http://sishuok.com/forum/blogPost/list/0/5814.html

---------------------------------------------------------------------------

0
0
分享到:
评论
1 楼 lockemn 2014-01-11  
不错啊,讲得很清晰易懂,就是图都无法显示,求楼主重新上传图片啊。

相关推荐

    研磨设计模式(完整带书签).part2.pdf

    本电子书一共两个压缩文档,本文件为part2. ...第23章 职责链模式(Chain of Responsibility) 第24章 桥接模式(Bridge) 第25章 访问者模式(Visitor) 附录A常见面向对象设计原则 附录BUML简介 参考文献

    研磨设计模式(完整带书签).part1.pdf

    本电子书一共两个压缩文档,该文档为part1。...第23章 职责链模式(Chain of Responsibility) 第24章 桥接模式(Bridge) 第25章 访问者模式(Visitor) 附录A常见面向对象设计原则 附录BUML简介 参考文献

    研磨设计模式带书签完整版228M.7z.001

    《研磨设计模式》完整覆盖GoF讲述的23个设计模式并加以细细研磨。初级内容从基本讲起,包括每个模式的定义、功能、思路、结构、基本实现、运行调用顺序、基本应用示例等,让读者能系统、完整、准确地掌握每个模式,...

    研磨设计模式源码

    研磨设计模式的配套源码,请下载,不要想了,解压后,直接放到eclipse下面即可运行!

    研磨设计模式-part2

    完整清晰版,完美书签. 《研磨设计模式》完整覆盖GoF...第23章 职责链模式(Chain of Responsibility) 第24章 桥接模式(Bridge) 第25章 访问者模式(Visitor) 附录A常见面向对象设计原则 附录BUML简介 参考文献

    研磨设计模式 完美书签 完整(一)

    《研磨设计模式》完整覆盖GoF讲述的23个设计模式并加以细细研磨。初级内容从基本讲起,包括每个模式的定义、功能、思路、结构、基本实现、运行调用顺序、基本应用示例等,让读者能系统、完整、准确地掌握每个模式,...

    研磨设计模式.part2(共4个)

    完整清晰版,完美书签. 《研磨设计模式》完整...第23章 职责链模式(Chain of Responsibility) 第24章 桥接模式(Bridge) 第25章 访问者模式(Visitor) 附录A常见面向对象设计原则 附录BUML简介 参考文献

    研磨设计模式-part4

    完整清晰版,完美书签. 《研磨设计模式》完整覆盖GoF...第23章 职责链模式(Chain of Responsibility) 第24章 桥接模式(Bridge) 第25章 访问者模式(Visitor) 附录A常见面向对象设计原则 附录BUML简介 参考文献

    研磨设计模式-part3

    完整清晰版,完美书签. 《研磨设计模式》完整覆盖GoF...第23章 职责链模式(Chain of Responsibility) 第24章 桥接模式(Bridge) 第25章 访问者模式(Visitor) 附录A常见面向对象设计原则 附录BUML简介 参考文献

    研磨设计模式带书签完整版228M.7z.002

    《研磨设计模式》完整覆盖GoF讲述的23个设计模式并加以细细研磨。初级内容从基本讲起,包括每个模式的定义、功能、思路、结构、基本实现、运行调用顺序、基本应用示例等,让读者能系统、完整、准确地掌握每个模式,...

    研磨设计模式-陈臣.epub

    “1.1 设计模式是什么 1.1.1 什么是模式 从字面上理解,模,就是模型、模板的意思;式,就是方式、方法的意思。综合起来,所谓模式就是:可以作为模型或模板的方式或方法。... “研磨设计模式”。 iBooks.

    研磨设计模式.part3(共4个)

    完整清晰版,完美书签. 《研磨设计模式》完整...第23章 职责链模式(Chain of Responsibility) 第24章 桥接模式(Bridge) 第25章 访问者模式(Visitor) 附录A常见面向对象设计原则 附录BUML简介 参考文献

    研磨设计模式.part4(共4个)

    完整清晰版,完美书签. 《研磨设计模式》完整...第23章 职责链模式(Chain of Responsibility) 第24章 桥接模式(Bridge) 第25章 访问者模式(Visitor) 附录A常见面向对象设计原则 附录BUML简介 参考文献

    研磨设计模式.part1(共4个)

    完整清晰版,完美书签. 《研磨设计模式》完整...第23章 职责链模式(Chain of Responsibility) 第24章 桥接模式(Bridge) 第25章 访问者模式(Visitor) 附录A常见面向对象设计原则 附录BUML简介 参考文献

    研磨设计模式(完整版pdf)part2 (2-3)

    研磨设计模式(完整版pdf)相信我不用介绍,很多人都在找这本书吧,今天我特意从另外的地方下载到了这本书,发了几十积分。才弄到。为了让大家同时分享这本书的精华。我今天特意上传。注:此电子书较大,我分了3个...

    研磨设计模式PDF

    研磨设计模式PDF

    研磨设计模式视频课程PPT

    内容概述:本视频课程是北京Java私塾原创精品书籍《研磨设计模式》一书的配套学习视频,由《研磨设计模式》的第一作者CC录制 课程目标:全面、系统的掌握GoF设计模式的知识,达到可以在实际项目开发中运用的能力 ...

    研磨设计模式-陈臣.王斌.扫描高清版PDF

    设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。 使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化;...

    研磨设计模式(完整版pdf) part1 (1-3)

    研磨设计模式(完整版pdf)相信我不用介绍,很多人都在找这本书吧,今天我特意从另外的地方下载到了这本书,发了几十积分。才弄到。为了让大家同时分享这本书的精华。我今天特意上传。注:此电子书较大,我分了3个...

    研磨设计模式高清完整版(2)

    《研磨设计模式》完整覆盖GoF讲述的23个设计模式并加以细细研磨。初级内容从基本讲起,包括每个模式的定义、功能、思路、结构、基本实现、运行调用顺序、基本应用示例等,让读者能系统、完整、准确地掌握每个模式,...

Global site tag (gtag.js) - Google Analytics