职责链模式-对象行为模式

意图:使多个对象有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。这将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
模式是给多个对象处理一个请求的机会,从而解耦发送者和接受者。请求沿对象链传递直至其中一个对象处理它,如下图所示:

从第一个对象开始,链中收到请求的对象要么亲自处理,要么转发给链中的下一个候选者。提交请求的对象并不明确的知道哪一个对象将会处理它。即改请求有一个隐式的接收者,这需要使链上的对象都有一致的处理请求与访问链上后继者的接口。例如HandleHelp,在基类中它的缺省操作是将请求转发给后继.子类可重定义提供自己的帮助,或者使用缺省实现转发该请求,即调用这个基类的方法。
适用性:
1 有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。
2 想在不明确指定接受者的情况下,想多个对象中的一个提交一个请求。
3 可处理一个请求的对象集合应被动态指定。
结构:


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


参与者:
Handler:定义一个处理请求的接口;(可选)实现后继链。
ConcreteHandler:
处理它所负责的请求;可访问它的后继者;如果可处理该请求,就处理,否则转发给后继者。
Client:向链上的具体处理者对象提交请求。
协作:
当客户提交一个请求时,请求沿链传递直至有一个ConcreteHandler对象负责处理它。
效果:
1 降低耦合度:一个对象无需知道哪一个对象处理其请求。可简化对象的相互连接。它们仅需保持一个指向后继的引用,而不需保持它所有的后选接受者的引用。
2 增强了给对象指派职责的灵活性:可以在运行时刻对该链进行动态的增加或修改来增加或改变处理一个请求那些职责。
3 不保证被接受:可能有的请求到链的末端都得不到处理。
实现:
1 实现后继者:a 定义新的连接 b 使用已有的链接(如果已有的链接支持所需的链)

2 连接后继者    3 请求表示

代码(又木有处理内存...):

//职责链模式
#ifndef RESPONSIBILITY_H
#define RESPONSIBILITY_H

#include <iostream>
using namespace std;

typedef int Topic;
const Topic NO_HELP_TOPIC = -1;
const Topic PRINT_TOPIC = 1;
const Topic PAPER_ORIENTATION_TOPIC = 2;
const Topic APPLICATION_TOPIC = 3;

//定义了处理帮助请求的接口
class HelpHandler
{
public:
    HelpHandler(HelpHandler* = 0, Topic = NO_HELP_TOPIC);
	virtual bool HasHelp();    //用于检查是否有一个相关的帮助主题
	virtual void SetHandler(HelpHandler*, Topic);
	virtual void HandleHelp();  //处理帮助
private:
	HelpHandler* _successer;
	Topic _topic;
};

//所有窗口组件都是Widget抽象类的子类,Widget也是HelpHandler
//的子类,因为所有的用户界面元素都可有相关的帮助。
class Widget : public HelpHandler
{
protected:
	//构造函数包括对包含它的窗口的引用和其自身的帮助主题
	Widget(Widget* parent, Topic t = NO_HELP_TOPIC);
private:
	Widget* _parent;
};

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

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

//职责链的末端,不是窗口组件,是HelpHandler的直接子类
class Application : public HelpHandler
{
public:
	Application(Topic t) : HelpHandler(0, t){}
	void HandleHelp();
};
#endif

#include "responsibility.h"

HelpHandler::HelpHandler(HelpHandler* h, Topic t)
	: _successer(h), _topic(t)
{

}

bool HelpHandler::HasHelp()
{
	//如果当前的主题不是NO_HELP_TOPIC,则说明为真
	return _topic != NO_HELP_TOPIC;
}

void HelpHandler::SetHandler(HelpHandler* h, Topic t)
{
	_successer = h;
	_topic = t;
}

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

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

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

}

//首先测试其自身是否有帮助主题,如果没有定义,则调用HelpHandler
//中的HandleHelp操作将该请求转发给它的后继者。如果有,则显示。
void Button::HandleHelp()
{
	if (HasHelp())
		cout << "提供button的帮助" << endl;
	else
		HelpHandler::HandleHelp();
}

//Diaglog的后继者不是一个窗口组件而是任意的帮助请求处理对象。
Dialog::Dialog(HelpHandler* h, Topic t) : Widget(0, t)
{
	SetHandler(h, t);
}

//后继者不是窗口组件而是任意的帮助请求处理对象。实例的后继是Application
void Dialog::HandleHelp()
{
	if (HasHelp())
		cout << "提供button的帮助" << endl;
	else
		HelpHandler::HandleHelp();
}

void Application::HandleHelp()
{
	cout << "一系列帮助" << endl;
}


#include "responsibility.h"

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

	button->HandleHelp();
	dialog->HandleHelp();
	application->HandleHelp();

	system("pause");
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值