zoukankan      html  css  js  c++  java
  • 设计模式之职责链模式

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

    类型:行为类模式

    类图:

    责任连模式的结构

            责任连模式的类图非常简单,它由一个抽象地处理类和它的一组实现类组成:

    • 抽象处理类:抽象处理类中主要包含一个指向下一处理类的成员变量nextHandler和一个处理请求的方法handRequest,handRequest方法的主要主要思想是,如果满足处理的条件,则有本处理类来进行处理,否则由nextHandler来处理。
    • 具体处理类:具体处理类主要是对具体的处理逻辑和处理的适用条件进行实现。

    适用场景:

    1、有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定;

    2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求;

    3、处理一个请求的对象集合应被动态指定。

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

          职责链模式的主要优点在于可以降低系统的耦合度,简化对象的相互连接,同时增强给对象指派职责的灵活性,增加新的请求处理类也很方便;其主要缺点在于不能保证请求一定被接收,且对于比较长的职责链,请求的处理可能涉及到多个处理对象,系统性能将受到一定影响,而且在进行代码调试时不太方便。
     

    在大学里面当班干部,时常要向上级申请各方面的东西。譬如申请全班外出秋游,普通同学将申请表交给班长,班长签字之后交给辅导员,辅导员批准之后上交到主任办公室…就是这样,一个请求(这里是一份申请表)有时候需要经过好几个级别的处理者(这里是辅导员、主任)的审查才能够最终被确定可行与否。

    在这里表现出来的是一个职责链,即不同的处理者对同一个请求可能担负着不同的处理方式、权限,但是我们希望这个请求必须到达最终拍板的处理者(否则秋游就没戏了)。这种关系就很适合使用职责链模式了。

    类图结构如下:

     代码实现如下:

    1. // 全局变量,接口类型  
    2. /**  
    3.  * 使用Java中的interface定义全局变量,可根据具体需要在   
    4.  * 具体的包中使用静态导入相关的全局变量,语法如下:   
    5.  *  import static package01.package02.*;  
    6.  */ 
    7. interface Levels {  
    8.     public static final int LEVEL_01 = 1;  
    9.     public static final int LEVEL_02 = 2;  
    10.     public static final int LEVEL_03 = 3;  
    1. // 抽象请求类  
    2. abstract class AbstractRequest {  
    3.     private String content = null;  
    4.  
    5.     public AbstractRequest(String content) {  
    6.         this.content = content;  
    7.     }  
    8.  
    9.     public String getContent() {  
    10.         return this.content;  
    11.     }  
    12.  
    13.     // 获得请求的级别  
    14.     public abstract int getRequestLevel();  
    1. // 具体请求类01  
    2. class Request01 extends AbstractRequest {  
    3.     public Request01(String content) {  
    4.         super(content);  
    5.     }  
    6.  
    7.     @Override 
    8.     public int getRequestLevel() {  
    9.         return Levels.LEVEL_01;  
    10.     }  
    11. }  
    12.  
    13. // 具体请求类02  
    14. class Request02 extends AbstractRequest {  
    15.     public Request02(String content) {  
    16.         super(content);  
    17.     }  
    18.  
    19.     @Override 
    20.     public int getRequestLevel() {  
    21.         return Levels.LEVEL_02;  
    22.     }  
    23. }  
    24.  
    25. // 具体请求类03  
    26. class Request03 extends AbstractRequest {  
    27.     public Request03(String content) {  
    28.         super(content);  
    29.     }  
    30.  
    31.     @Override 
    32.     public int getRequestLevel() {  
    33.         return Levels.LEVEL_03;  
    34.     }  
    1. // 抽象处理者类,  
    2. abstract class AbstractHandler {  
    3.     // 责任链的下一个节点,即处理者  
    4.     private AbstractHandler nextHandler = null;  
    5.  
    6.     // 捕获具体请求并进行处理,或是将请求传递到责任链的下一级别  
    7.     public final void handleRequest(AbstractRequest request) {  
    8.  
    9.         // 若该请求与当前处理者的级别层次相对应,则由自己进行处理  
    10.         if (this.getHandlerLevel() == request.getRequestLevel()) {  
    11.             this.handle(request);  
    12.         } else {  
    13.             // 当前处理者不能胜任,则传递至职责链的下一节点  
    14.             if (this.nextHandler != null) {  
    15.                 System.out.println("当前 处理者-0" + this.getHandlerLevel()  
    16.                         + " 不足以处理 请求-0" + request.getRequestLevel());  
    17.                   
    18.                 // 这里使用了递归调用  
    19.                 this.nextHandler.handleRequest(request);  
    20.             } else {  
    21.                 System.out.println("职责链上的所有处理者都不能胜任该请求...");  
    22.             }  
    23.         }  
    24.     }  
    25.  
    26.     // 设置责任链中的下一个处理者  
    27.     public void setNextHandler(AbstractHandler nextHandler) {  
    28.         this.nextHandler = nextHandler;  
    29.     }  
    30.  
    31.     // 获取当前处理者的级别  
    32.     protected abstract int getHandlerLevel();  
    33.  
    34.     // 定义链中每个处理者具体的处理方式  
    35.     protected abstract void handle(AbstractRequest request);  
    1. // 具体处理者-01  
    2. class Handler01 extends AbstractHandler {  
    3.     @Override 
    4.     protected int getHandlerLevel() {  
    5.         return Levels.LEVEL_01;  
    6.     }  
    7.  
    8.     @Override 
    9.     protected void handle(AbstractRequest request) {  
    10.         System.out.println("处理者-01 处理 " + request.getContent() + " ");  
    11.     }  
    12. }  
    13.  
    14. // 具体处理者-02  
    15. class Handler02 extends AbstractHandler {  
    16.     @Override 
    17.     protected int getHandlerLevel() {  
    18.         return Levels.LEVEL_02;  
    19.     }  
    20.  
    21.     @Override 
    22.     protected void handle(AbstractRequest request) {  
    23.         System.out.println("处理者-02 处理 " + request.getContent()+ " ");  
    24.     }  
    25. }  
    26.  
    27. // 具体处理者-03  
    28. class Handler03 extends AbstractHandler {  
    29.     @Override 
    30.     protected int getHandlerLevel() {  
    31.         return Levels.LEVEL_03;  
    32.     }  
    33.  
    34.     @Override 
    35.     protected void handle(AbstractRequest request) {  
    36.         System.out.println("处理者-03 处理 " + request.getContent()+ " ");  
    37.     }  
    1. // 测试类  
    2. public class Client {  
    3.     public static void main(String[] args) {  
    4.         // 创建指责链的所有节点  
    5.         AbstractHandler handler01 = new Handler01();  
    6.         AbstractHandler handler02 = new Handler02();  
    7.         AbstractHandler handler03 = new Handler03();  
    8.  
    9.         // 进行链的组装,即头尾相连,一层套一层  
    10.         handler01.setNextHandler(handler02);  
    11.         handler02.setNextHandler(handler03);  
    12.  
    13.         // 创建请求并提交到指责链中进行处理  
    14.         AbstractRequest request01 = new Request01("请求-01");  
    15.         AbstractRequest request02 = new Request02("请求-02");  
    16.         AbstractRequest request03 = new Request03("请求-03");  
    17.           
    18.         // 每次提交都是从链头开始遍历  
    19.         handler01.handleRequest(request01);  
    20.         handler01.handleRequest(request02);  
    21.         handler01.handleRequest(request03);  
    22.     }  

    测试结果:

    1. 处理者-01 处理 请求-01 
    2.  
    3. 当前 处理者-01 不足以处理 请求-02 
    4. 处理者-02 处理 请求-02 
    5.  
    6. 当前 处理者-01 不足以处理 请求-03 
    7. 当前 处理者-02 不足以处理 请求-03 
    8. 处理者-03 处理 请求-03 
    在上面抽象处理者 AbstractHandler 类的 handleRequest() 方法中,被 protected 修饰,并且该方法中调用了两个必须被子类覆盖实现的抽象方法,这里是使用了模板方法模式(Template Mehtod)。其实在这里,抽象父类的 handleRequest() 具备了请求传递的功能,即对某些请求不能处理时,马上提交到下一结点(处理者)中,而每个具体的处理者仅仅完成了具体的处理逻辑,其他的都不用理。
     
    记得第一次看到职责链模式的时候,我很惊讶于它能够把我们平时在代码中的 if..else.. 的语句块变成这样灵活、适应变化。例如:如果现在辅导员请长假了,但我们的秋游还是要争取申请成功呀,那么我们在 Client 类中可以不要创建 handler02,即不要将该处理者组装到职责链中。这样子处理比 if..else..好多了。或者说,突然来了个爱管闲事的领导,那么我照样可以将其组装到职责链中。
     
    关于上面使用场景中提到的3个点:
    1、处理者在运行时动态确定其实是我们在 Client 中组装的链所引起的,因为具体的职责逻辑就在链中一一对应起来;
    2、因为不确定请求的具体处理者是谁,所以我们把所有可能的处理者组装成一条链,在遍历的过程中就相当于向每个处理者都提交了这个请求,等待其审查。并且在审查过程中,即使不是最终处理者,也可以进行一些请求的“包装”操作(这种功能类似于装饰者模式),例如上面例子中的签名批准;
    3、处理者集合的动态指定跟上面的第1、2点类似,即在 Client 类中创建了所有可能的处理者。
     
    不足之处:

    1、对于每一个请求都需要遍历职责链,性能是个问题;

    2、抽象处理者 AbstractHandler 类中的 handleRequest() 方法中使用了递归,栈空间的大小也是个问题。

    参考:http://blog.csdn.net/zhengzhb/article/details/7568676

    http://haolloyin.blog.51cto.com/1177454/342166/

    http://blog.csdn.net/qq7342272/article/details/6921524

    http://blog.csdn.net/hguisu/article/details/7547231

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

    http://www.cnblogs.com/xudong-bupt/p/3617860.html

  • 相关阅读:
    032 Gradle 下载的依赖jar包在哪?
    031 can't rename root module,Android Studio修改项目名称
    030 Cannot resolve symbol'R' 问题解决汇总大全
    029 Android Studio层级显示目录文件
    028 You are about to commit CRLF line separators to the Git repository.It is recommended to set the core. autocrlf Git attribute to true to avoid line separator issues If you choose Fix and Comit ,
    027 【Android基础知识】Android Studio 编译慢及 Adb connection Error:远程主机强迫关闭了一个现有的连接
    026 Android Studio 和Gradle版版本对应关系
    025 Cause: org.jetbrains.plugins.gradle.tooling.util.ModuleComponentIdentifierIm
    024 Android Studio上传项目到Github 最全记录
    023 解决AndroidStudio下载gradle慢的问题
  • 原文地址:https://www.cnblogs.com/manmanlu/p/5732979.html
Copyright © 2011-2022 走看看