设计模式之职责链(chain of responsibility)---对象行为型模式

36 篇文章 0 订阅
16 篇文章 0 订阅

设计模式之职责链(chain of responsibility)---对象行为型模式

1.意图

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

2.适用性

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


3.结构(如图1)





一个典型的对象结构可能如下图所示:


4.参与者

*Handler
---定义一个处理请求的接口.
---(可选) 实现后继者.
*ConcreteHander
---处理它所负责的请求.
---可访问他的后继者.
---如果可处理该请求,就处理之; 否则将它转发给他的后继者.
* Client
---向链上的具体处理这( ConcreteHander) 对象提交该请求.

5.协作

当客户提交一个请求时,请求沿着链直至有一个ConcreteHander对象负责处理它.

6.代码及示例:

//本例实现一个文档的帮助系统,帮助沿着职责链上传.

class HelpHandler {
public:
HelpHandler(HelpHandler* s) : _successor(s) { }
virtual void HandleHelp();
private:
HelpHandler* _successor;
};

void HelpHandler::HandleHelp () {
if (_successor) {
_successor->HandleHelp();
}
}

class Request {
public:
int GetKind();
};
class HelpRequest : public Request {
};

class PrintRequest : public Request {
};


class Handler {
public:
virtual void HandleRequest(Request* theRequest);
void HandleHelp(HelpRequest*);
void HandlePrint(PrintRequest*);
};

const int Help = 1;
const int Print = 2;
const int Preview = 2;

void Handler::HandleRequest (Request* theRequest) {
switch (theRequest->GetKind()) {
case Help:
// cast argument to appropriate type
HandleHelp((HelpRequest*) theRequest);
break;

case Print:
HandlePrint((PrintRequest*) theRequest);
// ...
break;

default:
// ...
break;
}
}

class ExtendedHandler : public Handler {
public:
virtual void HandleRequest(Request* theRequest);
// ...
};

void ExtendedHandler::HandleRequest (Request* theRequest) {
switch (theRequest->GetKind()) {
case Preview:
// handle the Preview request
break;

default:
// let Handler handle other requests
Handler::HandleRequest(theRequest);
}
}


#include"defs.H"
class Application;
class Dialog;
class HelpHandler;

typedef int Topic;
const Topic NO_HELP_TOPIC = -1;

class HelpHandler {
public:
HelpHandler(HelpHandler* = 0, Topic = NO_HELP_TOPIC);
virtual bool HasHelp();
virtual void SetHandler(HelpHandler*, Topic);
virtual void HandleHelp();
private:
HelpHandler* _successor;
Topic _topic;
};

HelpHandler::HelpHandler (
HelpHandler* h, Topic t
) : _successor(h), _topic(t) { }

bool HelpHandler::HasHelp () {
return _topic != NO_HELP_TOPIC;
}

void HelpHandler::HandleHelp () {
if (_successor != 0) {
_successor->HandleHelp();
}
}

class Widget : public HelpHandler {
protected:
Widget(Widget* parent, Topic t = NO_HELP_TOPIC);
private:
Widget* _parent;
};

Widget::Widget (Widget* w, Topic t) : HelpHandler(w, t) {
_parent = w;
}

class Button : public Widget {
public:
Button(Widget* d, Topic t = NO_HELP_TOPIC);

virtual void HandleHelp();
// Widget operations that Button overrides...
};

Button::Button (Widget* h, Topic t) : Widget(h, t) { }

void Button::HandleHelp () {
if (HasHelp()) {
// offer help on the button
} else {
HelpHandler::HandleHelp();
}
}

class Dialog : public Widget {
public:
Dialog(HelpHandler* h, Topic t = NO_HELP_TOPIC);
virtual void HandleHelp();

// Widget operations that Dialog overrides...
// ...
};

Dialog::Dialog (HelpHandler* h, Topic t) : Widget(0) {
SetHandler(h, t);
}

void Dialog::HandleHelp () {
if (HasHelp()) {
// offer help on the dialog
} else {
HelpHandler::HandleHelp();
}
}

class Application : public HelpHandler {
public:
Application(Topic t) : HelpHandler(0, t) { }

virtual void HandleHelp();
// application-specific operations...
};

void Application::HandleHelp () {
// show a list of help topics
}

void dummy () {

const Topic PRINT_TOPIC = 1;
const Topic PAPER_ORIENTATION_TOPIC = 2;
const Topic APPLICATION_TOPIC = 3;

Application* application = new Application(APPLICATION_TOPIC);
Dialog* dialog = new Dialog(application, PRINT_TOPIC);
Button* button = new Button(dialog, PAPER_ORIENTATION_TOPIC);

button->HandleHelp();

}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值