您的位置:首页 > 大数据 > 人工智能

设计模式 笔记 责任链模式 chain of responsibility

2015-04-25 14:14 471 查看
//---------------------------15/04/25----------------------------

//Chain of responsibility 责任链-----对象行为型模式

/*

1:意图:

使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这些对象

连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

2:动机:

3:适用性:

1>有多个对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。

2>你想在不明确指定接受者的情况下,向多个对象中的一个
请求提交一个请求。

3>可处理一个请求的对象集合应被动态指定。

4:结构:



Client-------------->Handler:<---------

successor---------|

HandleRequest(){ successor->HandleRequest()}

|

-------------------

| |

ConcreteHandler1: ConcereteHandler2:

HandleRequest() HandleRequest()

{ if can handle

{ do something}

else

{ Handler::HandleRequest()}

}

5:参与者:

1>Handler:

1)定义一个处理请求的接口。

2)(可选)实现后继链。

2>ConcreteHandler

1)处理它所负责的请求。

2)可访问它的后继者。

3)如果可处理该请求,就处理之;否则将该请求转发给它的后继者。

3>Clinet

向链上的具体处理者对象提交请求。

6:协作:

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

7:效果:

优点:

1>降低耦合度:

该模式使得对象无需知道是其他哪一个对象处理其请求。接收者和发送者都没有对方的明确的

信息,且链中的对象不需知道链的结构。

所以责任链可简化对象的相互连接。

2>增强了给对象指派职责的灵活性:

可以在运行时刻动态增加或修改职责。

缺点:

1>不保证被接受。

既然一个请求没有明确的就收者,那么不能保证一定会被处理。

2>当链条太长时,会有效率问题(ps:这一点是我自己加的)

和明确指派任务相比,这么做或多或少会损失点效率,所以不能乱用。

8:实现:

1>实现后继者链:

1)定义新的链接:

没有已有链接时只能自己定义了。

2)使用已有的链接:

如果已经有个链接了,比如说Composite模式中定义了Parent的引用。直接拿来用就行了

也就是把父部件当作后继者,因为责任链一般都是向“上”传递的,也就是越往“上”越普通。



2>链接后继者:

如果是自己定义一个后继者链,Handler不仅要定义接口,通常也要维护链接。也就是要提供一个

缺省实现:向后继者转发请求。

3>表示请求:

1)硬编码:

也就是直接调用,这样只能表示一种请求类型。

2)使用处理函数:

通过传递参数来判断请求的类型。这就需要发送者和接收者在编码问题上达成一致。

9:代码示例: */

//定义了请求的类型

typedef int Topic;
const Topic NO_HELP_TOPIC = -1;

//Handler 定义了各种接口
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;
}

//调用后继者的HandleHelp()
void HelpHandler::HandleHelp()
{

if(_successor != 0)
_successor->HandleHelp();
}

//ConcreteHandler中的abstract类
听起来很奇怪,但是就是这样的

//很多东西都有帮助,窗口组件则一般都会有帮助,所以定义一个继承子Handler的abstract


//但是它确实也属于Handler的ConcreteHandler类,因为它指定了是窗口组件类。
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;
}

//ConcreteHandler:
具体的处理者。
class Button :
public Widget
{

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

virtual void HandleHelp();
};

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

//如果有帮助就调用,否则传递给后继者(如果有的话)。
void Button::HandleHelp()
{

if(HasHelp())
{



//do something
}

else
{
HelpHandler::HandleHelp();
}
}

//ConcreteHandler:类似上面,只不过它后继者可以是任意的帮助类,而不一定只是窗口类
class Dialog :
public Widget
{

public:
Dialog(HelpHandler* h, Topic = NO_HELP_TOPIC);

virtual void HandleHelp();
};

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

void Dialog::HandleHelp()
{

if(HasHelp())
{

//do something
}

else
{
HelpHandler::HandleHelp();
}
}

//ConcreteHandler:最后一个节点,没有后继者了。
class Application :
public HelpHandler
{
Application(Topic t) : HelpHandler(0, t){}

virtual void HandleHelp();
};

void Application::HandleHelp()
{

//do something
}

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有自己的帮助(PAPER_ORIENTATION_TOPIC)所以会自己处理,并不会交给后继者

//当然如果里面的do something中调用了Handler::HandlerHelp(),那么还是会传递下去的。
button->HandleHelp();
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐