什么是责任链模式
当外部请求程序进行某个处理,但程序暂时无法直接决定由哪个对象负责处理时,就需要推卸责任。这种情况下,我们可以考虑将多个对象组成一条职责链,然后按照他们在责任链上的顺序一个一个地找出到底应该谁来负责处理。
示例程序
Trouble类,表示需要处理的问题,结构很简单,只有一个问题号码,不同的号码交给不同的处理者处理。
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类,用来解决问题的抽象类。属性有类名,以及它的下一个处理者。有一个用来处理问题的模板方法support() 和 支持处理哪些编号问题的抽象方法resolve(),这个方法交给不同的子类实现,用以区分不同的子类可以处理哪些编号的问题。
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.");
}
}
具体解决问题的类,他们实现resolve的方式各不相同,分别用来解决某类编号的问题。注意NoSupport,它实现resolve的方式是直接返回false,表示不处理任何问题。
public class NoSupport extends Support {
public NoSupport(String name) {
super(name);
}
@Override
protected boolean resolve(Trouble trouble) {
return false;
}
}
public class LimitSupport extends Support {
private int limit;
public LimitSupport(String name, int limit) {
super(name);
this.limit = limit;
}
@Override
protected boolean resolve(Trouble trouble) {
return trouble.getNumber() < limit;
}
public class OddSupport extends Support {
public OddSupport(String name) {
super(name);
}
@Override
protected boolean resolve(Trouble trouble) {
return trouble.getNumber() % 2 == 1;
}
}
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) {
return trouble.getNumber() == number;
}
}
测试类
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 elmo = new OddSupport("elmo");
alice.setNext(bob).setNext(charlie).setNext(elmo);
// 制造各种问题
for (int i = 0; i < 500; i += 33) {
alice.support(new Trouble(i));
}
}
}
输出
[Trouble 0] is resolved by [bob].
[Trouble 33] is resolved by [bob].
[Trouble 66] is resolved by [bob].
[Trouble 99] is resolved by [bob].
[Trouble 132] cannot be resolved.
[Trouble 165] is resolved by [elmo].
[Trouble 198] cannot be resolved.
[Trouble 231] is resolved by [elmo].
[Trouble 264] cannot be resolved.
[Trouble 297] is resolved by [elmo].
[Trouble 330] cannot be resolved.
[Trouble 363] is resolved by [elmo].
[Trouble 396] cannot be resolved.
[Trouble 429] is resolved by [charlie].
[Trouble 462] cannot be resolved.
[Trouble 495] is resolved by [elmo].
为什么要用责任链模式
- 弱化了发出请求的人和处理请求的人之间的关系。以前的方式是,需要发出请求的人指定好谁去处理,做到一一对应;现在发出请求的人只需要丢给那一堆专门处理的人,是自己处理就处理,不是就往后传递。
- 可以动态地改变职责链。
- 专注于自己的工作。每个ConcreteHandler角色都专注于自己所负责的处理。