职责链模式(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. 自定义checkbox/radio

    一. label标签 1. 概念: HTML <label>元素表示用户界面中项目的标题.它通常关联一个控件,或者是将控件放置在label元素内,或者是用作其属性.这样的控制称作label ...

  2. 2017-2-28 C#基础 数组

    1.什么是数组? 数组就是具有相同数据类型变量的集合. 2.数组的作用:操作大量数据. 3.数组的定义要求:(1)数组里面的内容必须是同一类型.(2)数组必须有长度限制. 4.数组分为一维数组,二维数 ...

  3. 每天一个linux命令(40)--route命令

    Linux 系统的route 命令用于显示和操作IP路由表(show /manipulate the ip routing table).要实现两个不同的子网之间的通信,需要一台连接两个网络的路由器, ...

  4. Java版本

    Java版本 Java版本分为J2SE(Java 2 Standard Edition,Java标准版).J2ME(Java 2 Micro Edition,Java微型版本)和J2EE(Java 2 ...

  5. Spring框架---Spring入门

    Spring入门 为了能更好的理解先讲一些有的没的的东西: 什么是Spring Spring是分层的JavaSE/EE full-stack(一站式) 轻量级开源框架 分层 SUN提供的EE的三层结构 ...

  6. Ubuntu14.04: Error found when loading /root/.profile

    问题描述: 启用root账号登录后系统出现如下提示信息: Error found when loading /root/.profile stdin:is not a tty 解决方法: 在终端中用命 ...

  7. 局域网里连接mysql服务器,其他人连接自己的mysql服务器

    应用场景:  自己在自己的机器上开发网站,同事也要和我一起开发,就两个人,我自己的机器当做服务器,让他直接连我的数据库,看我的项目就行了,并且用svn进行开发,相当不错 问题: 怎样在局域网里,其他人 ...

  8. Java面试04|Spring框架

    1.动态代理的几种方式 Java主要有两种代理,JDK和Cglib动态代理.先看JDK代理实例如下: JDK创建代理有一个限制,即它只能为接口创建代理实例.举个例子如下: public interfa ...

  9. 20170305Meetup Git、heroku drop db

    Rails中,给link_to添加上action和class样式,内部文本 <%= link_to product_path(product),{ :controller => 'cont ...

  10. 1734: [Usaco2005 feb]Aggressive cows 愤怒的牛

    1734: [Usaco2005 feb]Aggressive cows 愤怒的牛 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 217  Solved: ...