Chain of Responsibility 职责链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
这一模式的想法是,给多个对象处理一个请求的机会,从而解耦发送者和接受者。该请求沿对象链传递直至其中一个对象处理它。从第一个对象开始,链中收到请求的对象要么亲自处理理它,要么转发给链中的下一个候选者。提交请求的对象并不明确地知道哪一个对象将会处理它--我们说该请求有一个隐式的接收者(implicit receiver)。要沿链转发请求,并保证接收者为隐式的(implicit),每个在链上的对象都有一致的处理请求接口和访问链上后继者的接口。
Chain of Responsibility 适用于:1.有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。2.你想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。3.可处理一个请求的对象集合应被动态指定。
Chain of Responsibility 的通用结构如下:
一个典型的对象结构可能如下所示:
参与者:
Handler: 定义一个处理请求的接口,缺省操作是将请求转发给后继。并在需要的情况下实现后继链,但也可以在 ConcreteHandler 中定义。
ConcreteHandler:处理它所负责的请求。可访问它的后继者。如下可处理该请求,就处理之;否则将该请求转发给它的后继者。
Client:向链上的具体处理者(concreteHandler)对象提交请求。当客户提交一个请求时,请求沿链传递直至有一个 ConcreteHandler 对象负责处理它。
Responsibility 链:1.降低耦合度,该模式使得一个对象无需知道是其它哪一个对象处理其请求。对象仅需要知道该请求会被“正确”地处理。接收者和发送者都没有对方的明确的信息,且链中的对象不需知道链的结构。结果是,职责链可简化对象的相互连接。它们仅需保持一个指向其后继者的引用,而不需保持它所有的候选接受者的引用。2.增强了给对象指派职责的灵活性,当在对象中分派职责时,职责链给你更多的灵活性。你可以在运行时刻对该链进行动态的增加或修改来增加或改变处理一个请求的那些职责。3.不保证被接受,既然一个请求没有明确的接收者,那么就不能保证它一定会被处理。
Chain of Responsibility 职责链模式代码示例:
1:
2: #pragma once
3:
4: #include
5:
6: // 抽象基类, 定义一个处理请求的接口
7: class Handler
8: {
9: public:
10: Handler(Handler *pSuccessor = NULL)
11: : m_pSuccessor(pSuccessor)
12: { }
13: virtual ~Handler()
14: {
15: delete m_pSuccessor;
16: m_pSuccessor = NULL;
17: }
18:
19: // 缺省情况下,将请求转发给后继者
20: virtual void HandleRequest()
21: {
22: if(m_pSuccessor)
23: m_pSuccessor->HandleRequest();
24: }
25:
26: protected:
27: Handler* m_pSuccessor;
28: };
29:
30: //ConcreateHandlerA 处理它所负责的请求,不能处理则转发给后继者
31: class ConcreateHandlerA : public Handler
32: {
33: public:
34: ConcreateHandlerA(Handler *pSuccessor = NULL)
35: : Handler(pSuccessor){ }
36: virtual ~ConcreateHandlerA(){ }
37:
38: virtual void HandleRequest()
39: {
40: if (NULL != m_pSuccessor)
41: {
42: m_pSuccessor->HandleRequest();
43: }
44: else
45: {
46: std::cout << "HandleRequest by ConcreateHandlerA" << std::endl;
47: }
48: }
49: };
50: //ConcreateHandlerB 处理它所负责的请求,不能处理则转发给后继者
51: class ConcreateHandlerB : public Handler
52: {
53: public:
54: ConcreateHandlerB(Handler *pSuccessor = NULL)
55: : Handler(pSuccessor){ }
56: virtual ~ConcreateHandlerB(){ }
57:
58: virtual void HandleRequest()
59: {
60: if (NULL != m_pSuccessor)
61: {
62: m_pSuccessor->HandleRequest();
63: }
64: else
65: {
66: std::cout << "HandleRequest by ConcreateHandlerB!" << std::endl;
67: }
68: }
69: };
//test
1:
2: #include "ChainOfResponsibility.h"
3:
4: int main()
5: {
6: Handler *p1 = new ConcreateHandlerA();
7: Handler *p2 = new ConcreateHandlerB(p1);
8:
9: p2->HandleRequest();
10:
11: delete p2;
12:
13: return EXIT_SUCCESS;
14: }
职责链(Chain of Responsibility)模式可以被看作一个使用策略对象的“递归的动态一般化”。此时提出一个调用,在一个链序列中的每个策略都试图满足这个调用。这个过程直到有一个策略成功满足该调用或者到达链序列的末尾才结束。在递归方法中,有个函数反复调用其自身直至达到某个终止条件;在职责链中,一个函数调用自身,(通过遍历策略链)调用函数的一个不同实现,如此反复直至达到某个终止条件。这个终止条件或者是已达到策略链的底部(这样就会返回一个默认对象;不管能否提供这个默认结果,必须有个方法能够决定该职责链搜索是成功还是失败)或者是成功找到一个策略。
除了调用一个函数来满足某个请求以外,链中的多个函数都有此机会满足某个请求,因此它有点专家系统的意味由于职责链实际上就是一个链表,它能够动态创建,因此它可以看做是一个更一般动态构建的 switch 语句。
//from Thinking in C++ volume 2
1:
2: #include
3: #include
4:
5: using namespace std;
6:
7: enum Answer { NO, YES };
8:
9: //Release Sequence
10: template<class Seq>
11: void Release(Seq& c)
12: {
13: typename Seq::iterator iter;
14: for(iter = c.begin(); iter != c.end(); ++iter)
15: {
16: delete *iter;
17: *iter = 0;
18: }
19: }
20:
21: //所有策略类和 Gimme(语境类)都派生自 GimmeStrategy
22: class GimmeStrategy
23: {
24: public:
25: virtual Answer canIHave() = 0;
26: virtual ~GimmeStrategy() {}
27: };
28:
29: class AskMom : public GimmeStrategy
30: {
31: public:
32: Answer canIHave()
33: {
34: cout << "Mooom? Can I have this?" << endl;
35: return NO;
36: }
37: };
38:
39: class AskDad : public GimmeStrategy {
40: public:
41: Answer canIHave()
42: {
43: cout << "Dad, I really need this!" << endl;
44: return NO;
45: }
46: };
47:
48: class AskGrandpa : public GimmeStrategy
49: {
50: public:
51: Answer canIHave()
52: {
53: cout << "Grandpa, is it my birthday yet?" << endl;
54: return NO;
55: }
56: };
57:
58: class AskGrandma : public GimmeStrategy
59: {
60: public:
61: Answer canIHave()
62: {
63: cout << "Grandma, I really love you!" << endl;
64: return YES;
65: }
66: };
67:
68: class Gimme : public GimmeStrategy
69: {
70: private:
71: vector
chain;
72: public:
73: Gimme()
74: {
75: chain.push_back(new AskMom());
76: chain.push_back(new AskDad());
77: chain.push_back(new AskGrandpa());
78: chain.push_back(new AskGrandma());
79: }
80: Answer canIHave()
81: {
82: vector
::iterator it = chain.begin();
83: while(it != chain.end())
84: {
85: if((*it++)->canIHave() == YES)
86: return YES;
87: }
88: // Reached end without success...
89: cout << "Whiiiiinnne!" << endl;
90: return NO;
91: }
92: ~Gimme()
93: {
94: Release(chain);
95: }
96: };
97:
98: int main()
99: {
100: Gimme chain;
101: chain.canIHave();
102:
103: return EXIT_SUCCESS;
104: }