设计模式(20):职责链模式CHAINOFRESPONSIBILITY

职责链模式

意图

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。


使用场景

在以下条件下使用职责链:

  • 有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。
  • 你想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
  • 可处理一个请求的对象集合应被动态指定。

结构

职责链模式结构如下
ShowImage

  • Handler

    – 定义一个处理请求的接口。

    – (可选) 实现后继链。

  • ConcreteHandler

    – 处理它所负责的请求。

    – 可访问它的后继者。

    – 如果可处理该请求,就处理之;否则将该请求转发给它的后继者。

  • Client

    – 向链上的具体处理者(ConcreteHandler)对象提交请求。

协作

当客户提交一个请求时,请求沿链传递直至有一个ConcreteHandler对象负责处理它。


效果

职责链有下列优点和缺点:

  • 降低耦合度

    该模式使得一个对象无需知道是其他哪一个对象处理其请求。对象仅需知道该请求会被“正确”地处理。接收者和发送者都没有对方的明确的信息,且链中的对象不需知道链的结构。结果是,职责链可简化对象的相互连接。它们仅需保持一个指向其后继者的引用,而不需保持它所有的候选接受者的引用。
  • 增强了给对象指派职责( Responsibility)的灵活性

    当在对象中分派职责时,职责链给你更多的灵活性。你可以通过在运行时刻对该链进行动态的增加或修改来增加或改变处理一个请求的那些职责。你可以将这种机制与静态地指定Handler的继承机制结合起来使用。
  • 不保证请求被接受

    既然一个请求没有明确的接收者,那么就不能保证它一定会被处理,该请求可能一直到链的末端都得不到处理。一个请求也可能因该链没有被正确配置而得不到处理。

职责链模式实现(Implement)

案例

某软件公司有初级工程师,高级工程师和领域专家三种层级的工程师,公司有新的需求时,会交给工程师来处理,一般先交给初级工程师来处理,如果搞不定就交给高级工程师,如果高级工程师也无法解决的话就由领域专家来处理,这个案例就可以使用职责链模式。

代码实现

开发者的抽象类,对应模式中的Handler

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
/* 抽象的工程师类,对应模式中的Handler */
public abstract class Developer {
protected Developer nextDeveloper;
public void setNextDeveloper(Developer developer) {
nextDeveloper = developer;
}
//处理请求的判断逻辑
public final void handleRequest(Request request) {
if (getLevel() >= request.getLevel()) {
//如果层级一致交给该工程师来处理
handle(request);
} else {
//否则交给下一级来处理
if (nextDeveloper != null) {
System.out.println("当前工程师无法解决,交给下一级工程师解决...");
nextDeveloper.handleRequest(request);
} else {
//如果都不能处理
System.out.println("所有工程师都不能处理该问题");
}
}
}
//当前工程师能处理的层级
public abstract int getLevel();
//具体的处理方法
public abstract void handle(Request request);
}

抽象的请求类

1
2
3
4
5
6
7
8
9
/* 抽象的请求类 */
public abstract class Request {
//请求具体的内容
public abstract String getProblemContent();
//获取当前问题的层级
public abstract int getLevel();
}

初级工程师,对应模式中的ConcreateHandler

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/* 初级工程师,ConcreteHandler in pattern */
public class AssociateDeveloper extends Developer {
private static final int EASY_LEVEL = 1;
@Override
public int getLevel() {
return EASY_LEVEL;
}
@Override
public void handle(Request request) {
System.out.println(request.getProblemContent());
System.out.println("初级工程师已经解决简单问题...");
}
}

高级工程师,对应模式中的ConcreateHandler

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/* 高级工程师,ConcreteHandler in pattern */
public class SeniorDeveloper extends Developer {
private static final int HARD_LEVEL = 2;
@Override
public int getLevel() {
return HARD_LEVEL;
}
@Override
public void handle(Request request) {
System.out.println(request.getProblemContent());
System.out.println("高级工程师已经解决比较困难的问题...");
}
}

领域专家,对应模式中的ConcreateHandler

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/* 领域专家,ConcreteHandler in pattern */
public class ExpertDeveloper extends Developer {
public static final int VERY_HARD_LEVEL = 3;
@Override
public int getLevel() {
return VERY_HARD_LEVEL;
}
@Override
public void handle(Request request) {
System.out.println(request.getProblemContent());
System.out.println("领域专家已经解决相当棘手的问题...");
}
}

简单需求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class EasyRequest extends Request {
private static final int EASY_LEVEL = 1;
@Override
public String getProblemContent() {
return "简单的问题描述:………………";
}
@Override
public int getLevel() {
return EASY_LEVEL;
}
}

比较困难的需求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class HardRequest extends Request {
private static final int HARD_LEVEL = 2;
@Override
public String getProblemContent() {
return "比较困难的问题描述:………………";
}
@Override
public int getLevel() {
return HARD_LEVEL;
}
}

相当棘手的需求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class VeryHardRequest extends Request {
private static final int VERY_HARD_LEVEL = 3;
@Override
public String getProblemContent() {
return "相当棘手的问题描述:………………";
}
@Override
public int getLevel() {
return VERY_HARD_LEVEL;
}
}

Client调用,并且动态地指定了职责链的successor

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
42
43
44
45
46
47
48
49
public class ChainOfResponsibilityDemoTest {
@Test
public void developersHandleRequests() {
System.out.println("-----A公司有三个级别的工程师-----");
//初级工程师
Developer developerC = new AssociateDeveloper();
//高级工程师
Developer developerA = new SeniorDeveloper();
//领域专家
Developer developerS = new ExpertDeveloper();
developerC.setNextDeveloper(developerA);
developerA.setNextDeveloper(developerS);
//A公司来了个简单的需求
System.out.println("A公司来了个简单的需求");
Request requestA = new EasyRequest();
System.out.println("交给初级工程师处理");
developerC.handleRequest(requestA);
System.out.println("----------");
//A公司来了个比较困难的需求
System.out.println("A公司来了个比较困难的需求");
Request requestB = new HardRequest();
System.out.println("交给初级工程师处理");
developerC.handleRequest(requestB);
System.out.println("----------");
//A公司来了个十分棘手的需求
System.out.println("A公司来了个十分棘手的需求");
Request requestC = new VeryHardRequest();
System.out.println("交给高级工程师处理");
developerA.handleRequest(requestC);
System.out.println("----------");
//A公司又来了一个比较困难的需求
System.out.println("A公司又来了一个比较困难的需求");
Request requestD = new HardRequest();
System.out.println("交给领域专家处理");
developerS.handleRequest(requestD);
}
}

运行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
-----A公司有三个级别的工程师-----
A公司来了个简单的需求
交给初级工程师处理
简单的问题描述:………………
初级工程师已经解决简单问题...
----------
A公司来了个比较困难的需求
交给初级工程师处理
当前工程师无法解决,交给下一级工程师解决...
比较困难的问题描述:………………
高级工程师已经解决比较困难的问题...
----------
A公司来了个十分棘手的需求
交给高级工程师处理
当前工程师无法解决,交给下一级工程师解决...
相当棘手的问题描述:………………
领域专家已经解决相当棘手的问题...
----------
A公司又来了一个比较困难的需求
交给领域专家处理
比较困难的问题描述:………………
领域专家已经解决相当棘手的问题...
Process finished with exit code 0

总结

职责链的核心在于将接收者和发送者解耦并且为请求创建了一条接收者的处理链。职责链模式又分为纯的职责链模式和不纯的职责链模式。纯的职责链模式是指一个请求必须被某一个Handler接收,不能出现某个请求未被任何一个Handler处理的情况。不纯的职责链模式是允许某个请求被一个Handler部分处理后再向下传递,或者一个Handler处理完某请求后其successor可以继续处理该请求,而且一个请求可以最终不被任何Handler所接收。上面的例子就是一个不纯的职责链模式,如果所有工程师都无法搞定,那么请求就无法被任意一个Handler处理。

参考代码

------ 本文结束 ------

版权声明


BillyYccc's blog by Billy Yuan is licensed under a Creative Commons BY-NC-SA 4.0 International License.
本文原创于BillyYccc's Blog,转载请注明原作者及出处!