责任链模式是一种行为设计模式, 允许你将请求沿着处理者链进行发送。 收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者。
即将所有处理某种请求的对象一个接一个的排成序列,当某个任务来临时,按照次序列依次执行下去,直至有对象处理。
责任链模式是一个很贴近生活的设计模式,使每个对象做好自己分内的事情即可。当一个请求来的时候,当前处理对象不能处理,那就交给下一个处理对象,至于是谁处理无需关心。
另外,请求只要被某个对象处理了,就直接返回,不会继续执行下去。从而保证请求不会被多次处理。
电脑打开了多个软件窗口(TIM、Chrome、WeChat),三个窗口有重叠的部分。实现鼠标选定不同的软件窗口。
上述场景,鼠标的点击事件可以看成一种请求,当点击到某个软件窗口的范围内则表示选中该软件。如果点击到软件窗口重叠的部分,就默认选中最顶部的软件。
软件实现:将软件从最顶端到最底端排成链型,当收到点击请求时,按照链顺序依次访问软件类,是否需要执行此请求即可。
实现方式较简单,CViewBase派生出的子类在运行中持有一个CViewBase对象,并在HandleRequest处理外部请求,当此对象不能处理时,便丢给持有的CViewBase对象去处理。
编程环境
工程结构
ChainOfResponsibility/
├── app_view.cc
├── app_view.h
├── main.cc
└── Makefile
基类接口
class CViewBase
{
public:
CViewBase()
{}
virtual ~CViewBase()
{}
virtual void SetNextHandler(CViewBase* handler) = 0;
virtual void HandleRequest(void *request) = 0;
};
定义各app窗口接口,主要在于统一各个子类处理请求的接口。
Chrome类接口
class CChromeView : public CViewBase
{
public:
explicit CChromeView(int XBegin, int XEnd, int YBegin, int YEnd);
void SetNextHandler(CViewBase* handler);
void HandleRequest(void *request);
bool IsSelect(SClickLocation *location);
private:
int mXBegin;
int mXEnd;
int mYBegin;
int mYEnd;
CViewBase *mNextHandler;
};
Chrome类定义了此窗口的位置坐标,以及重载了基类的接口HandleRequest。
注册下一责任类
void CChromeView::SetNextHandler(CViewBase* handler)
{
mNextHandler = handler;
}
此接口用于实例化该类持有的CViewBase对象,该对象在责任链上的顺序位于CChromeView之后。
请求处理接口实现
void CChromeView::HandleRequest(void *request)
{
if (!request) {
VIEW_LOGE("request is invaild!\n");
}
if (IsSelect((SClickLocation *)request)) {
VIEW_LOGI("Click Chrome!\n");
} else {
VIEW_LOGD("Next handler!\n");
if (mNextHandler) {
mNextHandler->HandleRequest(request);
}
}
}
bool CChromeView::IsSelect(SClickLocation *location)
{
bool ret = false;
if ( location->locX > mXBegin && location->locX < mXEnd
&& location->locY > mYBegin && location->locY < mYEnd
)
{
ret = true;
}
return ret;
}
当鼠标点击的坐标位于CChromeView内,则处理此请求;否则,丢给下一个类去处理。
其他子类业务与此相同,不再列举。
规定责任链顺序
static void init()
{
// 设置责任链顺序: theTim -> theChrome -> theWeChat
theChrome.SetNextHandler(&theWeChat);
theTim.SetNextHandler(&theChrome);
}
规定请求执行对象的顺序依次为theTim -> theChrome -> theWeChat
客户端接口
int main(int argc, char *argv[])
{
init();
SClickLocation clickEvent1 = {28, 42}; // 点击坐标(28, 42), Chrome
theTim.HandleRequest(&clickEvent1);
SClickLocation clickEvent2 = {48, 62}; // 点击坐标(48, 62), WeChat
theTim.HandleRequest(&clickEvent2);
SClickLocation clickEvent3 = {12, 20}; // 点击坐标(12, 20), Tim
theTim.HandleRequest(&clickEvent3);
return 0;
}
$ ./exe
Click Chrome!
Click WeChat!
Click Tim!
职责链模式存在以下两种情况:
优点
缺点
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。