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

适用场景:

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;
  11. }
  1. // 抽象请求类
  2. abstract class AbstractRequest {
  3. private String content = null;
  4. public AbstractRequest(String content) {
  5. this.content = content;
  6. }
  7. public String getContent() {
  8. return this.content;
  9. }
  10. // 获得请求的级别
  11. public abstract int getRequestLevel();
  12. }
  1. // 具体请求类01
  2. class Request01 extends AbstractRequest {
  3. public Request01(String content) {
  4. super(content);
  5. }
  6. @Override
  7. public int getRequestLevel() {
  8. return Levels.LEVEL_01;
  9. }
  10. }
  11. // 具体请求类02
  12. class Request02 extends AbstractRequest {
  13. public Request02(String content) {
  14. super(content);
  15. }
  16. @Override
  17. public int getRequestLevel() {
  18. return Levels.LEVEL_02;
  19. }
  20. }
  21. // 具体请求类03
  22. class Request03 extends AbstractRequest {
  23. public Request03(String content) {
  24. super(content);
  25. }
  26. @Override
  27. public int getRequestLevel() {
  28. return Levels.LEVEL_03;
  29. }
  30. }
  1. // 抽象处理者类,
  2. abstract class AbstractHandler {
  3. // 责任链的下一个节点,即处理者
  4. private AbstractHandler nextHandler = null;
  5. // 捕获具体请求并进行处理,或是将请求传递到责任链的下一级别
  6. public final void handleRequest(AbstractRequest request) {
  7. // 若该请求与当前处理者的级别层次相对应,则由自己进行处理
  8. if (this.getHandlerLevel() == request.getRequestLevel()) {
  9. this.handle(request);  
  10. } else {
  11. // 当前处理者不能胜任,则传递至职责链的下一节点
  12. if (this.nextHandler != null) {
  13. System.out.println("当前 处理者-0" + this.getHandlerLevel()
  14. + " 不足以处理 请求-0" + request.getRequestLevel());
  15. // 这里使用了递归调用
  16. this.nextHandler.handleRequest(request);  
  17. } else {
  18. System.out.println("职责链上的所有处理者都不能胜任该请求...");
  19. }
  20. }
  21. }
  22. // 设置责任链中的下一个处理者
  23. public void setNextHandler(AbstractHandler nextHandler) {
  24. this.nextHandler = nextHandler;
  25. }
  26. // 获取当前处理者的级别
  27. protected abstract int getHandlerLevel();
  28. // 定义链中每个处理者具体的处理方式
  29. protected abstract void handle(AbstractRequest request);
  30. }
  1. // 具体处理者-01
  2. class Handler01 extends AbstractHandler {
  3. @Override
  4. protected int getHandlerLevel() {
  5. return Levels.LEVEL_01;
  6. }
  7. @Override
  8. protected void handle(AbstractRequest request) {
  9. System.out.println("处理者-01 处理 " + request.getContent() + "\n");
  10. }
  11. }
  12. // 具体处理者-02
  13. class Handler02 extends AbstractHandler {
  14. @Override
  15. protected int getHandlerLevel() {
  16. return Levels.LEVEL_02;
  17. }
  18. @Override
  19. protected void handle(AbstractRequest request) {
  20. System.out.println("处理者-02 处理 " + request.getContent()+ "\n");
  21. }
  22. }
  23. // 具体处理者-03
  24. class Handler03 extends AbstractHandler {
  25. @Override
  26. protected int getHandlerLevel() {
  27. return Levels.LEVEL_03;
  28. }
  29. @Override
  30. protected void handle(AbstractRequest request) {
  31. System.out.println("处理者-03 处理 " + request.getContent()+ "\n");
  32. }
  33. }
  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. handler01.setNextHandler(handler02);
  10. handler02.setNextHandler(handler03);
  11. // 创建请求并提交到指责链中进行处理
  12. AbstractRequest request01 = new Request01("请求-01");
  13. AbstractRequest request02 = new Request02("请求-02");
  14. AbstractRequest request03 = new Request03("请求-03");
  15. // 每次提交都是从链头开始遍历
  16. handler01.handleRequest(request01);
  17. handler01.handleRequest(request02);
  18. handler01.handleRequest(request03);
  19. }
  20. }

测试结果:

  1. 处理者-01 处理 请求-01
  2. 当前 处理者-01 不足以处理 请求-02
  3. 处理者-02 处理 请求-02
  4. 当前 处理者-01 不足以处理 请求-03
  5. 当前 处理者-02 不足以处理 请求-03
  6. 处理者-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() 方法中使用了递归,栈空间的大小也是个问题。

个人看法:

职责链模式对于请求的处理是不知道最终处理者是谁,所以是运行动态寻找并指定;而命令模式中对于命令的处理时在创建命令是已经显式或隐式绑定了接收者。

职责链模式(Chain of Responsibility)的Java实现的更多相关文章

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

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

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

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

  3. 职责链模式(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)摘录

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

  7. 行为型设计模式之职责链模式(Chain of Responsibility)

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

  8. 职责链模式(chain of responsibility)

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

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

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

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

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

随机推荐

  1. XHTML表格

    1.基本格式: <table> <tr> <th>A</th><th>B</th><th>C</th>& ...

  2. java springmvc +spring+ mybaits 模块化开发框架 HTML5+css3.0+bootstrap响应式开发界面

    需要源码,请加QQ:858-048-581 系统模块 1.   权限管理:点开二级菜单进入三级菜单显示 角色(基础权限)和按钮权限       角色(基础权限): 分角色组和角色,独立分配菜单权限和增 ...

  3. 服务器 'XXXXXX' 上的 MSDTC 不可用。解决方法

    今天在C#中操作数据库的时候突然发现这个问题:服务器 'USER-XXX' 上的 MSDTC 不可用. 解决方法: 在windows控制面板 --> 管理工具 --> 服务 --> ...

  4. 使用java.util.Properties类读写配置文件

    J2SE 1.5 以前的版本要求直接使用 XML 解析器来装载配置文件并存储设置,虽说也并非难事,相比 java.util.Properties却要做额外的解析工作.而java.util.Proper ...

  5. js实现浏览器添加收藏功能

    今天搞项目的时候为了实现浏览者实现添加收藏的功能,特地了解了一下相关的API. 也看到了网上各种版本的代码.整理了一下,代码如下.简单易懂. <script> function _addF ...

  6. C++设计模式:Template Method

    我使用过一个简单的后台服务框架.这个框架上手很容易,我只需要继承一个基类,同时实现,或重写(override)基类声明的几个接口(这些接口声明为虚函数,或者纯虚函数),然后调用基类定义好的run()函 ...

  7. 每天一个Linux命令 9

    Linux常用命令: 压缩命令:gzip 解压命令:gunzip 压缩命令:zip  解压命令:unzip 压缩命令:bzip2  解压命令:bunzip2 压缩打包命令:tar 1.命令名称:gzi ...

  8. android开发艺术探索读书笔记之-------view的事件分发机制

    View的点击事件的分发,其实就是对MotionEvent事件的分发过程,即当一个MotionEvent产生后,系统需要把这个事件传递给一个具体的View,而这个过程就是分发过程. 分发过程主要由以下 ...

  9. solr home 目录设置

    对于在tomcat 中部署solr 来说,有以下三处可以配置 solr.solr.home(即solr的数据文件位置): 1. 在解压缩solr.war后的webapps/solr 中的WEB-INF ...

  10. 【NFS项目实战二】NFS共享数据的时时同步推送备份

    [NFS项目实战二]NFS共享数据的时时同步推送备份 标签(空格分隔): Linux服务搭建-陈思齐 ---本教学笔记是本人学习和工作生涯中的摘记整理而成,此为初稿(尚有诸多不完善之处),为原创作品, ...