JDON中china of Responsibility模式的疑惑?

08-09-16 ITfuture
大家好:
这两天看了关于设计模式中职责链模式chain of Responsibility。我觉得它就是通过引用来决定下一个处理单位的.
使用这个模式接偶发送者和调用者之间的关系,也就是说发送者无需知道当前链上的那个对象进行处理。这样系统可以在不影响客户调用的情况下动态组织链和分配责任。
看了3种方式的演示后,比如例子中:
public class ConcreteHandler implements Handler{
  private Handler successor;

  public ConcreteHandler(Handler successor){
    this.successor=successor;
  }

  public void handleRequest(Request request){
    if (request instanceof HelpRequest){
      //这里是处理Help的具体代码
    }else if (request instanceof PrintRequst){
      request.execute();
    }else
      //传递到下一个
      successor.handle(request);

    }
  }
}
其中方法handleRequest里的实现我始终是不解?
顺便问问BANQ 在这个COR中,如果我增加一种处理format是不是应该增加一个formatHandler和一个formatRequest?
当我处于客户端调用的时候
问题是当我生成ConcreteHandler 类实例时候必然要给 他传 下一个的处理对象?那不是跟我上面说的概念相互矛盾么?
莫非我太局限于当前实例的代码?但是我怎么也明白不过来COR带来的
【发送者无需知道当前链上的那个对象进行处理。这样系统可以在不影响客户调用的情况下动态组织链和分配责任】
可能我的表达让大家会有误解,希望高人来解道啊!天天在线等...谢谢大家了


1
freebox
2008-09-16 17:27
发表一下我的理解:
链是什么样的呢?是一环一环的,这一环的前后是什么东西只有这一环自己知道
于是构造个接口:

interface Manager{
  void manageIt(int price);
  Manager setNextManager(Manager manager);
}
abstract class AbstractManager implements Manager{
  protected Manager next;
  Manager setNextManager(Manager manager){
    this.next=manager;
  }
}
<p class="indent">

再构造几个环子:

class ManagerOne extends AbstractManager{
  void manageIt(int price){
    if(price<=100){
      debug("here is One.I can manage it,do not post next,stop here");
    }else{
      next.manageIt(price);
    }
  }
}
class ManagerTwo extends AbstractManager{
  void manageIt(int price){
    if(price<=1000){
      debug("here is Two.");
    }else{
      next.manageIt(price);
    }
  }
}
class ManagerThree extends AbstractManager{
  void manageIt(int price){
    if(price<=10000){
      debug("here is Three.");
    }else{
      next.manageIt(price);
    }
  }
}
class ManagerLast extends AbstractManager{
  void manageIt(int price){
    if(price>10000){
      debug("here is Last.");
    }else{
      debug("What happened?why here?");
      throw new RuntimeException();
    }
  }
}
<p class="indent">

在客户端把环子串起来并实施调用

class Client{
  //invoke it before
  void init(){
    Manager one=new ManagerOne();
    Manager two=new ManagerTwo();
    Manager three=new ManagerThree();
    Manager last=new ManagerLast();
    one.setNextManager(two);
    two.setNextManager(three);
    three.setNextManager(last);
  }
  void test(){
    //数字200发言:其实我不知道到底哪个环在处理我,只要从第一个开始就可以了
    //它处理不了我也不知道,反正有一个环处理了,或者到最后扔回来一个异常。
    one.manageIt(200);
  }
}
<p class="indent">

[该贴被freebox于2008-09-16 17:35修改过]

ITfuture
2008-09-16 17:55
初始链的关系和分配责任是在客户端来完成的么?如果是的话哪么链还是暴露给了客户端。实际上客户端还是在维护这个链的关系。
当前COR的使用前提是
1 处理请求者如果无法确定请求内容.
2 需要将请求处理机制和请求内容解耦,才会使用CoR

根据你的测试代码加上BANQ上的测试代码的话估计1 2前提是有的。
但是客户端应该不应该去维护这个链的关系和分配责任。

事实上客户端调用到底是什么样的我还是很糊涂...可能是经验不到。望大家给予指点。。谢谢楼上回复

freebox
2008-09-17 08:04
init是由配置决定的,可以注入进去,因为省略了配置所以才写在init里,实际应用时客户端是看不到它的。甚至可以只声明接口为public,其它环声明成包访问级别,客户端根本就得不到其它的引用。
class Client{
private Manager first;
public void setManager(Manager manager){
this.first=manager;
}
public void test(){
first.manageIt(200);
}
}
环的构成用注入,Client的第一个环也注入。

[该贴被freebox于2008-09-17 08:11修改过]

ITfuture
2008-09-17 09:00
谢谢你的解释.我似乎了解了...呵呵。感觉自己有点钻牛角尖,没有彻底想透一个链的本质.
在回头看BANQ的代码。他将链的责任和处理分别划分到
HANDLER和REQUEST。
这样在增加一种链处理的时候。客户端完全不需要知道。并且不需要改动代码。只需要重新理清链之间的关系就可以。
谢谢FREEBOX。谢谢你的无私。哈哈
不知道我理解的是否正确?

banq
2008-09-17 09:16
>,如果我增加一种处理format是不是应该增加一个formatHandler和一个formatRequest?

需要类似一个handleRequest的方法,其实参考servletFilter就可以,ServletFilter是一个典型的COR模式,每个Filter方法都要调用chain方法以便传递到下一个Filter.

>当我处于客户端调用的时候
问题是当我生成ConcreteHandler 类实例时候必然要给 他传 下一个的处理对象

生成实例其实涉及对象创建,使用IOC/factory模式来解决。

猜你喜欢