0%

设计模式之Chain of Responsibility模式

责任链模式介绍

简单说,责任链模式可以说是, 当问题不能解决的时候,将问题交给另一个对象去处理,就这样一直传递下去直至当前对象找不到下线了,处理结束.

  • 意图: 避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。

  • 主要解决:职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。

  • 应用实例:

    • JS 中的事件冒泡。
    • JAVA WEB 中 Apache Tomcat 对 Encoding 的处理,Struts2 的拦截器,jsp servlet 的 Filter。
  • 优点:

    • 降低耦合度。它将请求的发送者和接收者解耦。
    • 简化了对象。使得对象不需要知道链的结构。
    • 增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
    • 增加新的请求处理类很方便。
  • 缺点:

    • 不能保证请求一定被接收。
    • 系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
    • 可能不容易观察运行时的特征,有碍于除错。
  • 使用场景:

  • 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。

  • 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。

  • 可动态指定一组对象处理请求。

示例程序

  • 程序1:

Trouble类 (数据结构)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.edu.tju.GOF.ChainOfResponsibility;

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类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package com.edu.tju.GOF.ChainOfResponsibility;

public abstract class Support {

protected abstract boolean resolve(Trouble trouble);

String name;
Support next;

public Support(String name) {
this.name = name;
}

public String toString() {
return "[" + name + "]";
}

public Support setAndReturnNext(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);
}
}

protected void fail(Trouble trouble) {
System.out.println(trouble + "cannot be resolved.");
}

protected void done(Trouble trouble) {
System.out.println(trouble + " is resolved by "+this+ ".");
}

}

NoSupport类

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.edu.tju.GOF.ChainOfResponsibility;

public class NoSupport extends Support {

public NoSupport(String name) {
super(name);
}

protected boolean resolve(Trouble trouble) {
return false;
}

}

LimitSupport类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.edu.tju.GOF.ChainOfResponsibility;

public class LimitSupport extends Support {

private int limit;

public LimitSupport(String name, int limit) {
super(name);
this.limit = limit;
}

protected boolean resolve(Trouble trouble) {
return trouble.getNumber() <= limit ? true : false;
}

}

SpecialSupport类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.edu.tju.GOF.ChainOfResponsibility;

public class SpecialSupport extends Support {

public int specialNumber;

public SpecialSupport(String name, int specialNumber) {
super(name);
this.specialNumber = specialNumber;
}

protected boolean resolve(Trouble trouble) {
return trouble.getNumber() == specialNumber ? true : false;
}

}

OddSupport类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.edu.tju.GOF.ChainOfResponsibility;


public class OddSupport extends Support {

public OddSupport(String name) {
super(name);
}

protected boolean resolve(Trouble trouble) {
return (trouble.getNumber()%2) == 1 ? true : false;
}

}

Main类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.edu.tju.GOF.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.setAndReturnNext(bob).setAndReturnNext(charlie).setAndReturnNext(diana).setAndReturnNext(elmo)
.setAndReturnNext(fred);
// 制造各种问题
for (int i = 0; i < 10; i += 1) {
alice.support(new Trouble((int)(Math.random()*500)));
}
}
}

角色

核心是Handle类,里面使用模板方法定义好了调用链的逻辑,然后通过递归调用下一个处理人。其它ConcreteHandler只负责定义各自的业务处理逻辑,然后等待被调用就行

  • Handle(处理者,抽象类)
  • ConcreteHandler(具体的处理者)
  • Client(请求者)
  • Chain of Responsibility模式的类图

Thank you for your support