Java api中设计模式之责任链(Chain-of-Responsibility)模式
这是一个行为型设计模式。
若干个Java AWT GUI 组件使用责任链设计模式来处理特定的事件。比如说,类java.awt.Button 覆盖了java.awt.Component类的processEvent方法,来处理AWTEvent对象。方法processEvent试图在作为一个参数接收到AWTEvent事件时处理它。如果方法processEvent判断AWTEvent是一个ActionEvent(即,这个Button已经被按下),该方法通过调用方法processActionEvent(该方法通知所有的相关ActionListener,该Button已经被按下)来处理该事件。如果方法processEvent判断此AWTEvent不是一个ActionEvent,那么该方法无法处理此事件,并将这个AWTEvent传递给超类Component(链中的下一个对象)的方法processEvent。
在面向对象系统中,对象之间通过彼此发送消息来进行交互。通常,系统需要在运行时决定用来处理某条特定消息的对象。比如说,考虑三线办公室电话系统的设计。当一个人拨打该办公室的电话时,第一条线路处理这个电话,如果此线路比较忙,那么由第二条线路进行处理,如果第二条线路忙,有第三条线路处理。如果所有线路都忙,自动扬声器会提示打电话者等待----当某条线路空闲的时候,该线路处理此电话。
责任链设计模式使得系统可以在运行时决定处理一条消息的对象。这个模式允许一个对象可以向处于一个对象链条中的若干对象发送消息。链条中的每一个对象或者处理消息,或者将此消息传递给下一个对象。
意图:
使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这些对象组成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
动机:
这儿的问题是提交帮助请求的对象(如按钮)并不知道谁是最终提供帮助信息的对象。我们要有一种办法将提交帮助请求的对象与可能提供帮助信息的对象解耦。
要沿着链转发请求,并保证接受者始终是隐式的,链上的每个对象都分享一致的的处理请求和访问链上后继者的接口。
实现:
那个一致的接口:
typedef int Topic;
const Topic NO_HELP_TOPIC = -1;
class HelpHandler {
public:
HelpHander(HelpHandler * = 0, Topic = NO_HELP_TOPIC);
virtual bool HasHelp();
virtual void SetHandler(HelpHandler*, Topic);
virtual void HandleHelp(); //处理请求,默认处理是将请求传递给后继者;一致的处理请求和访问后继者的接口
private:
HelpHandler* _successor; //自引用,链上的后继者 , 靠这个指针将他们组成一个链
Topic _topic;
};
void HelpHandler::HandleHelp() {
if (_successor != 0) {
_successor->HandleHelp();
}
}
class Widget : public HelpHandler {};
class Button : public Widget {};
class Dialog : public Widget {};
class Application : public HelpHandler{};
使用:
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-> dialog ->application。
button->HandleHelp(); //通过调用HandleHelp方法来发出一个请求。因为对于button对象来说,HasHelp()返回真,所以请求直接得到处理,而没有顺着链传递。