收藏私塾在线
 

欢迎您来到私塾在线网!   

请登录! 

免费注册 


javasscc的笔记
状态: 离线
人气:489381
访问用户量:1120
笔记经验:1858
总积分:1958
级别:普通会员
搜索本笔记
ta的交流分类
ta的交流主题贴(196)
ta的所有交流贴(200)
ta的全部笔记
全部笔记(98)
未分类笔记(0)
研磨设计模式(94)
课程问题(0)
设计模式综合项目实战(4)
存档
2013-05(4)
2012-08(39)
2012-07(55)

2012-08-24 09:54:03
研磨设计模式 之 职责链模式(Chain of Responsibility)2——跟着cc学设计系列
浏览(4242)|评论(0)   交流分类:Java|笔记分类: 研磨设计模式

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

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

相关笔记推荐
精品视频课程推荐

研磨设计模式——跟着cc学设计系列视频教程
本视频课程是北京Java私塾原创精品书籍《研磨设计模式》一书的配套学习视频,由《研磨设计模式》的第一作者CC录制 课程目标:全面、系统的掌握GoF设计模式的知识,达到可以在实际项目开发中运用的能力 技术要点:如何实现可配置、如何实现缓存以及缓存的管理、如何实现用缓存来控制多实例的创建、如何实现参数化工厂、 如何实现可扩展工厂、如何实现原型管理器、如何实现Java的静态代理和动态代理、如何实现多线程处理队列请求、 如何实现命令的参数化配置、可撤销的操作、宏命令、队列请求和日志请求、如何实现翻页迭代、如何检测环状结构、 如何实现通用的增删改查、如何模拟工作流来处理流程、如何实现简单又通用的XML读取、如何实现模拟AOP的功能......

freevoice(局域网对讲机)——Android4项目实战视频教程
实现通过Wifi来在局域网内相互传递信息和语音通话的功能;学习Service;Broadcast Receiver;SharedPreference;SQLite;语音录制、播放、传输等;网络开发:wifi处理、UDP编程、TCP编程;多种设计模式的应用 等等

软件系统功能设计实战训练视频教程
本课程是《软件系统功能设计实战训练》网络班的全套学习视频,通过6个具体的设计案例,综合应用几乎全部的GoF设计模式,以及多种设计理念和方法。 每个设计案例都各有侧重点,训练的难度会逐步加大,以切实帮助各位学员快速的掌握软件系统设计的方法,提升自己的软件系统设计能力。

深入浅出学Spring Web MVC视频教程
系统、完整的学习Spring Web MVC开发的知识。包括:Spring Web MVC入门;理解DispatcherServlet;注解式控制器开发详解;数据类型转换;数据格式化;数据验证; 拦截器;对Ajax的支持;文件上传下载;表单标签等内容;最后以一个综合的CRUD带翻页的应用示例来综合所学的知识

《设计模式综合项目实战》——跟着cc学设计系列精品视频教程

浏览(4242)|评论(0)   交流分类:Java|笔记分类: 研磨设计模式

评论(0)
请登录后评论 登录

关于我们 | 联系我们 | 用户协议 | 私塾在线服务协议 | 版权声明 | 隐私保护

版权所有 Copyright(C)2009-2012 私塾在线学习网