》》
----- 当外部请求程序进行某个处理,但程序暂时无法直接决定由哪个对象负责处理时,就需要推卸责任。
在这种情况下,我们可以考虑将多个对象组成一条职责链,然后按照它们的职责链上的顺序一个一个
地找出到底应该谁来负责处理。
----- 使用 Chain of Responsibility 模式可以弱化“请求方”和“处理方”之间的关联关系,让双方各自都成为
独立复用的组件。此外,程序还可以应对其他需求,如根据需求不同,负责处理的对象也会发生变化
的这种需求。
------ 当一个人被要求做什么事情时,如果他可以做就自己做,如果不能做就将“要求”转给另外一个人。
下一个人如果可以自己处理,就自己做;如果也不能自己处理,就再转给另外一个人。。。。。这就
是推卸责任模式。
》》示例程序如下
》》Trouble 类
package chainofresponsibility; /** * Trouble 类是表示发生的问题的类。 * number 是问题编号;通过 getNumber 方法可以获取问题编号 */ public class Trouble { private int number; // 问题编号 public Trouble(int number){ // 生成问题 this.number = number; } public int getNumber(){ // 获取问题编号 return number; } public String toString(){ // 代表问题的字符串 return "[Trouble"+number + "]"; } }
》》Support 类
package chainofresponsibility; /** * Support 类是用来解决问题的抽象类,它是职责链上的对象。 * * */ public abstract class Support { private String name ; // 解决问题的实例的名字 private Support next; // 要推卸给的对象 public Support(String name){ this.name = name ; // 生成解决问题的实例 } public Support setNext(Support next){ // 设置要推卸给的对象 this.next = next; return next; } public final void support(Trouble trouble){ // 解决问题的步骤 if(resolve(trouble)){ done(trouble); }else if(next != null){ next.support(trouble); }else{ fail(trouble); } } public String toString(){ // 显示字符串 return "["+ name +"]"; } protected abstract boolean resolve(Trouble trouble); // 解决问题的方法 protected void done(Trouble trouble){ // 解决 System.out.println(trouble + "is resolved by " + this + "."); } protected void fail(Trouble trouble){ // 未解决 System.out.println(trouble + " cannot be resolved"); } }
》》 NoSupport 类
package chainofresponsibility; /** * NoSupport 类是 Support 类的子类。 * NoSupport 类的 resolve 方法总是返回 false 。即它是一个永远“不解决问题” 的类 */ public class NoSupport extends Support{ public NoSupport(String name){ super(name); } @Override protected boolean resolve(Trouble trouble) { // 解决问题的方法 return false; // 自己什么也不处理 } }
》》LimitSupport 类
package chainofresponsibility; /** * LimitSupport 类解决编号小于 limit 值的问题 */ public class LimitSupport extends Support{ private int limit ; // 可以解决编号小于 limit 的问题 public LimitSupport(String name, int limit ){ // 构造函数 super(name); this.limit = limit; } @Override protected boolean resolve(Trouble trouble) { // 解决问题的方法 if(trouble.getNumber() <limit){ return true; }else{ return false; } } }
》》OddSupport 类
package chainofresponsibility; /** * OddSupport 类解决奇数编号的问题 */ public class OddSupport extends Support{ public OddSupport(String name ){ // 构造函数 super(name); } @Override protected boolean resolve(Trouble trouble) { // 解决问题的方法 if(trouble.getNumber() % 2 ==1 ){ return true; }else{ return false; } } }
》》SpecialSupport 类
package chainofresponsibility; /** * SpecialSupport 类只解决指定编号的问题 */ public class SpecialSupport extends Support{ private int number; // 只能解决指定编号的问题 public SpecialSupport(String name , int number){ // 构造函数 super(name); this.number = number; } @Override protected boolean resolve(Trouble trouble) { // 解决问题的方法 if(trouble.getNumber() == number){ return true; }else{ return false; } } }
》》Main 类
package chainofresponsibility; /** * 测试程序 */ public class Main { public static void main(String[] args){ Support alice = new NoSupport("Alice"); Support bob = new LimitSupport("Bob",100); Support charlie = new SpecialSupport("Charlie",429); Support diana = new LimitSupport("Diana",200); Support elmo = new OddSupport("Elmo"); Support fred = new LimitSupport("Fred",300); // 形成职责链 alice.setNext(bob).setNext(charlie).setNext(diana).setNext(elmo).setNext(fred); // 制造各种问题 for(int i = 0 ; i < 500 ; i += 33){ alice.support(new Trouble(i)); } } }
》》Chain of Responsibility 模式中的登场角色
------ Handler (处理者)
Handler 角色定义了处理请求的接口(API)。Handler 角色知道“下一个处理者”是谁,如果自己
无法处理请求,它会将请求转给“下一个处理者”。当然“下一个处理者”也是 Handler 角色。在上面的
程序中, 由 Support 类扮演此角色。负责处理请求的是 support 方法。
------- ConcreteHandler(具体的处理者)
ConcreteHandler 角色是处理请求的具体角色。在上面的程序中,由 NoSupport 、 LimitSupport 、
OddSupport 、 SpecialSupport 等各个类扮演此角色。
------- Client (请求者)
Clinet 角色是第一个 ConcreteHandler 角色发送请求的角色。在上面的程序中,由 Main 类扮演
此角色。
》》扩展思路的要点
--------- 弱化了发送请求的人和处理请求的人之间的关系
Chain of Responsibility 模式的最大优点就在于它弱化了发出请求的人(Client 角色)和处理请求
的人(ConcreteHandler 角色)之间的关系。Client 角色向第一个 ConcreteHandler 角色发出的请求,
然后请求会在职责链中传播,直到某个 ConcreteHandler 角色处理该请求。
如果不使用该模式,就必须有某个伟大的角色知道“谁应该处理什么请求”。而让“发出请求的人”
知道“谁应该处理该请求”并不明智,因为如果发出请求的人不得不知道处理请求的人各自的责任分担
情况,就会降低其作为可复用的组件的独立性。
-------- 可以动态地改变职责链
使用 Chain of Responsibility 模式,通过委托推卸责任,就可以根据情况变化动态地重组织职责链。
-------- 专注于自己的工作
每个 ConcreteHandler 角色都专注于自己所负责的处理。当自己无法处理时,ConcreteHandler 角色
将会改当前问题丢给下一个处理者来解决。
--------- 推卸请求会导致处理延迟
使用 Chain of Responsibility 模式可以推卸请求,直到找到合适的处理请求的对象,这样确实提高了
程序的灵活性,但是该模式会导致处理请求发生延迟。
上面的问题是需要权衡的问题。如果请求和处理者之间的关系是确定的,而且需要非常快的处理速度
时,不使用 Chain of Responsibility 模式会更好。
》》相关的设计模式
-------- Composite 模式
Handler 角色经常会使用 Composite 模式。
-------- Command 模式
有时候会使用 Command 模式向 Handler 角色发送请求。