C++责任链模式
<上一节
下一节>
由遇到的问题引出责任链模式
熟悉 VC/MFC 的都知道,VC 是"基于消息,事件驱动",消息在 VC 开发中起着举足轻 重 的 作 用 。 在 MFC 中 , 消 息 是 通 过 一 个 向 上 递 交 的 方 式 进 行 处 理 , 例 如 一 个WM_COMMAND 消息的处理流程可能为:
MFC 提供了消息的处理的链式处理策略,处理消息的请求将沿着预先定义好的路径依次进行处理。消息的发送者并不知道该消息最后是由那个具体对象处理的,当然它也无须也不想知道,但是结构是该消息被某个对象处理了,或者一直到一个终极的对象进行处理了。
责任链模式描述其实就是这样一类问题将可能处理一个请求的对象链接成一个链,并将请求在这个链上传递,直到有对象处理该请求(可能需要提供一个默认处理所有请求的类,例如 MFC 中的 CwinApp 类)。
图 2-1:责任链模式结构图
责任链模式中 ConcreteHandler 将自己的后继对象(向下传递消息的对象)记录在自己的后继表中,当一个请求到来时,ConcreteHandler 会先检查看自己有没有匹配的处理程序,如果有就自己处理,否则传递给它的后继。当然这里示例程序中为了简化,ConcreteHandler 只是简单的检查看自己有没有后继,有的话将请求传递给后继进行处理,没有的话就自己处理。
代码片断 1:Handle.h
//Handle.h
#ifndef _HANDLE_H_
#define _HANDLE_H_
class Handle{
public:
virtual ~Handle();
virtual void HandleRequest() = 0;
void SetSuccessor(Handle* succ);
Handle* GetSuccessor();
protected:
Handle();
Handle(Handle* succ);
private:
Handle* _succ;
};
class ConcreteHandleA:public Handle{
public:
ConcreteHandleA();
~ConcreteHandleA();
ConcreteHandleA(Handle* succ);
void HandleRequest();
protected:
private:
};
class ConcreteHandleB:public Handle{
public:
ConcreteHandleB();
~ConcreteHandleB();
ConcreteHandleB(Handle* succ);
void HandleRequest();
protected:
private:
};
#endif //~_HANDLE_H_
代码片断 2:Handle.cpp
//Handle.cpp
#include "Handle.h"
#include <iostream>
using namespace std;
Handle::Handle(){
_succ = 0;
}
Handle::~Handle(){
delete _succ;
}
Handle::Handle(Handle* succ){
this->_succ = succ;
}
void Handle::SetSuccessor(Handle* succ){
_succ = succ;
}
Handle* Handle::GetSuccessor(){
return _succ;
}
void Handle::HandleRequest(){
}
ConcreteHandleA::ConcreteHandleA(){
}
ConcreteHandleA::ConcreteHandleA(Handle* succ):Handle(succ){
}
ConcreteHandleA::~ConcreteHandleA(){
}
void ConcreteHandleA::HandleRequest(){
if (this->GetSuccessor() != 0){
cout<<"ConcreteHandleA 我把处理权给后继节点....."<<endl;
this->GetSuccessor()->HandleRequest();
}
else{
cout<<"ConcreteHandleA 没有后继了,我必须自己处理...."<<endl;
}
}
ConcreteHandleB::ConcreteHandleB(){
}
ConcreteHandleB::ConcreteHandleB(Handle* succ):Handle(succ){
}
ConcreteHandleB::~ConcreteHandleB(){
}
void ConcreteHandleB::HandleRequest(){
if (this->GetSuccessor() != 0){
cout<<"ConcreteHandleB 我把处理权给后继节点....."<<endl;
this->GetSuccessor()->HandleRequest();
}
else{
cout<<"ConcreteHandleB 没有后继了,我必须自己处理...."<<endl;
}
}
码片断 3:main.cpp
//main.cpp
#include "Handle.h"
#include <iostream>
using namespace std;
int main(int argc,char* argv[]){
Handle* h1 = new ConcreteHandleA();
Handle* h2 = new ConcreteHandleB();
h1->SetSuccessor(h2);
h1->HandleRequest();
return 0;
}
代码说明:责任链模式的示例代码实现很简单,这里就其测试结果给出说明:ConcreteHandleA 的对象和 h1 拥有一个后继 ConcreteHandleB 的对象 h2,当一个请求到来时候,h1 检查看自己有后继,于是 h1 直接将请求传递给其后继 h2 进行处理,h2 因为没有后继,当请求到来时候,就只有自己提供响应了。于是程序的输出为:
熟悉 VC/MFC 的都知道,VC 是"基于消息,事件驱动",消息在 VC 开发中起着举足轻 重 的 作 用 。 在 MFC 中 , 消 息 是 通 过 一 个 向 上 递 交 的 方 式 进 行 处 理 , 例 如 一 个WM_COMMAND 消息的处理流程可能为:
- MDI 主窗口(CMDIFrameWnd)收到命令消息 WM_COMMAND,其 ID 位 ID_×××;
- MDI 主窗口将消息传给当前活动的 MDI 子窗口(CMDIChildWnd);
- MDI 子窗口给自己的子窗口(View)一个处理机会,将消息交给 View;
- View 检查自己 Message Map;
- 如果 View 没有发现处理该消息的程序,则将该消息传给其对应的 Document 对象;否则 View 处理,消息流程结束。
- Document 检查自己 Message Map,如果没有该消息的处理程序,则将该消息传给其对象的 DocumentTemplate 处理;否则自己处理,消息流程结束;
- 如果在⑥中消息没有得到处理,则将消息返回给 View;
- View 再传回给 MDI 子窗口;
- MDI 子窗口将该消息传给 CwinApp 对象,CwinApp 为所有无主的消息提供了处理。
MFC 提供了消息的处理的链式处理策略,处理消息的请求将沿着预先定义好的路径依次进行处理。消息的发送者并不知道该消息最后是由那个具体对象处理的,当然它也无须也不想知道,但是结构是该消息被某个对象处理了,或者一直到一个终极的对象进行处理了。
责任链模式描述其实就是这样一类问题将可能处理一个请求的对象链接成一个链,并将请求在这个链上传递,直到有对象处理该请求(可能需要提供一个默认处理所有请求的类,例如 MFC 中的 CwinApp 类)。
模式选择
责任链模式典型的结构图为:图 2-1:责任链模式结构图
责任链模式中 ConcreteHandler 将自己的后继对象(向下传递消息的对象)记录在自己的后继表中,当一个请求到来时,ConcreteHandler 会先检查看自己有没有匹配的处理程序,如果有就自己处理,否则传递给它的后继。当然这里示例程序中为了简化,ConcreteHandler 只是简单的检查看自己有没有后继,有的话将请求传递给后继进行处理,没有的话就自己处理。
关于责任链模式的实现
完整代码示例(code):责任链模式的实现比较简单,这里为了方便初学者的学习和参考,将给出完整的实现代码(所有代码采用 C++实现,并在 VC 6.0 下测试运行)。代码片断 1:Handle.h
//Handle.h
#ifndef _HANDLE_H_
#define _HANDLE_H_
class Handle{
public:
virtual ~Handle();
virtual void HandleRequest() = 0;
void SetSuccessor(Handle* succ);
Handle* GetSuccessor();
protected:
Handle();
Handle(Handle* succ);
private:
Handle* _succ;
};
class ConcreteHandleA:public Handle{
public:
ConcreteHandleA();
~ConcreteHandleA();
ConcreteHandleA(Handle* succ);
void HandleRequest();
protected:
private:
};
class ConcreteHandleB:public Handle{
public:
ConcreteHandleB();
~ConcreteHandleB();
ConcreteHandleB(Handle* succ);
void HandleRequest();
protected:
private:
};
#endif //~_HANDLE_H_
代码片断 2:Handle.cpp
//Handle.cpp
#include "Handle.h"
#include <iostream>
using namespace std;
Handle::Handle(){
_succ = 0;
}
Handle::~Handle(){
delete _succ;
}
Handle::Handle(Handle* succ){
this->_succ = succ;
}
void Handle::SetSuccessor(Handle* succ){
_succ = succ;
}
Handle* Handle::GetSuccessor(){
return _succ;
}
void Handle::HandleRequest(){
}
ConcreteHandleA::ConcreteHandleA(){
}
ConcreteHandleA::ConcreteHandleA(Handle* succ):Handle(succ){
}
ConcreteHandleA::~ConcreteHandleA(){
}
void ConcreteHandleA::HandleRequest(){
if (this->GetSuccessor() != 0){
cout<<"ConcreteHandleA 我把处理权给后继节点....."<<endl;
this->GetSuccessor()->HandleRequest();
}
else{
cout<<"ConcreteHandleA 没有后继了,我必须自己处理...."<<endl;
}
}
ConcreteHandleB::ConcreteHandleB(){
}
ConcreteHandleB::ConcreteHandleB(Handle* succ):Handle(succ){
}
ConcreteHandleB::~ConcreteHandleB(){
}
void ConcreteHandleB::HandleRequest(){
if (this->GetSuccessor() != 0){
cout<<"ConcreteHandleB 我把处理权给后继节点....."<<endl;
this->GetSuccessor()->HandleRequest();
}
else{
cout<<"ConcreteHandleB 没有后继了,我必须自己处理...."<<endl;
}
}
码片断 3:main.cpp
//main.cpp
#include "Handle.h"
#include <iostream>
using namespace std;
int main(int argc,char* argv[]){
Handle* h1 = new ConcreteHandleA();
Handle* h2 = new ConcreteHandleB();
h1->SetSuccessor(h2);
h1->HandleRequest();
return 0;
}
代码说明:责任链模式的示例代码实现很简单,这里就其测试结果给出说明:ConcreteHandleA 的对象和 h1 拥有一个后继 ConcreteHandleB 的对象 h2,当一个请求到来时候,h1 检查看自己有后继,于是 h1 直接将请求传递给其后继 h2 进行处理,h2 因为没有后继,当请求到来时候,就只有自己提供响应了。于是程序的输出为:
- ConcreteHandleA 我把处理权给后继节点.....;
- ConcreteHandleB 没有后继了,我必须自己处理....。
关于责任链模式的讨论
责任链模式的最大的一个有点就是给系统降低了耦合性,请求的发送者完全不必知道该请求会被哪个应答对象处理,极大地降低了系统的耦合性。
<上一节
下一节>