0 引言
0.1 目的
本文档给出设计模式之——Chain of Responsibility模式的简化诠释,并给出其C++实现。
0.2 说明
Project |
Design Pattern Explanation(By K_Eckel) |
Authorization |
Free Distributed but Ownership Reserved |
Date |
|
Test Bed |
MS Visual C++ 6.0 |
0.3 参考
在本文档的写作中,参考了以下的资源,在此列出表示感谢:
u 书籍
[GoF 2000]:GoF,Design Patterns-Elements of Reusable Object-Oriented Software
Addison-Wesley 2000/9.
[Martine 2003]:Robert C.Martine, Agile Software Development Principles, Patterns, and Practices, Pearson Education, 2003.
0.4 联系作者
Author |
K_Eckel |
State |
Candidate for Master’s Degree School of |
E_mail |
2 Chain of Responsibility模式
2.1 问题
熟悉VC/MFC的都知道,VC是“基于消息,事件驱动”,消息在VC开发中起着举足轻重的作用。在MFC中,消息是通过一个向上递交的方式进行处理,例如一个WM_COMMAND消息的处理流程可能为:
1) MDI主窗口(CMDIFrameWnd)收到命令消息WM_COMMAND,其ID位ID_×××;
2) MDI主窗口将消息传给当前活动的MDI子窗口(CMDIChildWnd);
3) MDI子窗口给自己的子窗口(View)一个处理机会,将消息交给View;
4) View检查自己Message Map;
5) 如果View没有发现处理该消息的程序,则将该消息传给其对应的Document对象;否则View处理,消息流程结束。
6) Document检查自己Message Map,如果没有该消息的处理程序,则将该消息传给其对象的DocumentTemplate处理;否则自己处理,消息流程结束;
7) 如果在6)中消息没有得到处理,则将消息返回给View;
8) View再传回给MDI子窗口;
9) MDI子窗口将该消息传给CwinApp对象,CwinApp为所有无主的消息提供了处理。
注明:有关MFC消息处理更加详细信息,请参考候捷先生的《深入浅出MFC》。
MFC提供了消息的处理的链式处理策略,处理消息的请求将沿着预先定义好的路径依
次进行处理。消息的发送者并不知道该消息最后是由那个具体对象处理的,当然它也无须也不想知道,但是结构是该消息被某个对象处理了,或者一直到一个终极的对象进行处理了。
Chain of Responsibility模式描述其实就是这样一类问题将可能处理一个请求的对象链接成一个链,并将请求在这个链上传递,直到有对象处理该请求(可能需要提供一个默认处理所有请求的类,例如MFC中的CwinApp类)。
2.2 模式选择
Chain of Responsibility模式典型的结构图为:
图2-1:Chain of Responsibility Pattern结构图
Chain of Responsibility模式中ConcreteHandler将自己的后继对象(向下传递消息的对象)记录在自己的后继表中,当一个请求到来时,ConcreteHandler会先检查看自己有没有匹配的处理程序,如果有就自己处理,否则传递给它的后继。当然这里示例程序中为了简化,ConcreteHandler只是简单的检查看自己有没有后继,有的话将请求传递给后继进行处理,没有的话就自己处理。
2.3 实现
2.3.1 完整代码示例(code)
Chain of Responsibility模式的实现比较简单,这里为了方便初学者的学习和参考,将给出完整的实现代码(所有代码采用C++实现,并在VC 6.0下测试运行)。
代码片断1:Handle.h #ifndef _HANDLE_H_ class Handle virtual void HandleRequest() = 0; void SetSuccessor(Handle* succ); Handle* GetSuccessor(); protected: Handle(Handle* succ); private: class ConcreteHandleA:public Handle ~ConcreteHandleA(); ConcreteHandleA(Handle* succ); void HandleRequest(); protected: private: }; class ConcreteHandleB:public Handle ~ConcreteHandleB(); ConcreteHandleB(Handle* succ); void HandleRequest(); protected: private: }; |
代码片断2:Handle.cpp #include "Handle.h" #include <iostream> using namespace std; Handle::Handle() Handle::~Handle() Handle::Handle(Handle* succ) void Handle::SetSuccessor(Handle* succ) Handle* Handle::GetSuccessor() void Handle::HandleRequest() } ConcreteHandleA::ConcreteHandleA() } ConcreteHandleA::ConcreteHandleA(Handle* succ):Handle(succ) } ConcreteHandleA::~ConcreteHandleA() } void ConcreteHandleA::HandleRequest() ConcreteHandleB::ConcreteHandleB() } ConcreteHandleB::ConcreteHandleB(Handle* succ):Handle(succ) } ConcreteHandleB::~ConcreteHandleB() } void ConcreteHandleB::HandleRequest() |
码片断3:main.cpp #include "Handle.h" #include <iostream> using namespace std; int main(int argc,char* argv[]) Handle* h2 = new ConcreteHandleB(); h1->SetSuccessor(h2); h1->HandleRequest(); return 0; |
2.3.2 代码说明
Chain of Responsibility模式的示例代码实现很简单,这里就其测试结果给出说明:
ConcreteHandleA的对象和h1拥有一个后继ConcreteHandleB的对象h2,当一个请求到来时候,h1检查看自己有后继,于是h1直接将请求传递给其后继h2进行处理,h2因为没有后继,当请求到来时候,就只有自己提供响应了。于是程序的输出为:
1) ConcreteHandleA 我把处理权给后继节点.....;
2) ConcreteHandleB 没有后继了,我必须自己处理....。
2.4 讨论
Chain of Responsibility模式的最大的一个有点就是给系统降低了耦合性,请求的发送者完全不必知道该请求会被哪个应答对象处理,极大地降低了系统的耦合性。