Chain Of Responsibility,职责链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接收之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
组成:
抽象处理者:它定义了一个处理请求的接口。
具体处理者:实现抽象处理者的接口,并处理它所负责的请求,如果不能处理则请问它的后继者。
纯的职责链模式,规定一个具体处理者对请求只能做两种动作:自己处理,传给下家。这里根据编码需求可以做些调整,比如:处理者可以对请求做部分处理,将其余部分传给下家处理。
这种设计模式比较简单也比较常用,比如:UI框架中的事件处理,事件最先传给最子层的当前焦点控件,调用其处理事件的接口,不处理向其父节点传递,这样逐层链式传递形成一个职责链。
代码示例:
class HelpHandler { public: enum THelpTopic { EPRINT_HELP_TOPIC, ECONFIRM_HELP_TOPIC, EAPPLICATION_HELP_TOPIC, ENO_HELP_TOPIC }; public: HelpHandler(HelpHandler* aHandler = NULL, THelpTopic aTopic = ENO_HELP_TOPIC) : iSuccessor(aHandler), iTopic(aTopic) { } virtual bool HasHelp() { return iTopic != ENO_HELP_TOPIC; } virtual void SetHandler(HelpHandler* aHandler, THelpTopic aTopic) { iSuccessor = aHandler; iTopic = aTopic; } virtual void HandleHelp() { if (iSuccessor) iSuccessor->HandleHelp(); } private: THelpTopic iTopic; HelpHandler* iSuccessor;//后继 }; class Widget : public HelpHandler { protected: Widget(Widget* aParent, THelpTopic aTopic = ENO_HELP_TOPIC) : HelpHandler(aParent, aTopic), iParent(aParent) { } private: Widget* iParent; }; class Button : public Widget { public: Button(Widget* aParent, THelpTopic aTopic = ENO_HELP_TOPIC) : Widget(aParent, aTopic) { } void HandleHelp() { if (HasHelp()) { //显示自己help信息的代码,即链传递停止 } else { HelpHandler::HandleHelp();//留给它的successor去处理 } } }; class Dialog : public Widget { Dialog(HelpHandler* h, THelpTopic aTopic = ENO_HELP_TOPIC) : Widget(NULL) { SetHandler(h, aTopic); } void HandleHelp() { if (HasHelp()) { //显示自己help信息的代码,即链传递停止 } else { HelpHandler::HandleHelp();//留给它的successor去处理 } } }; class Application : public HelpHandler { public: Application(THelpTopic aTopic) : HelpHandler(NULL, aTopic){} void HandleHelp() { //显示自己help信息的代码,不再向下传递 } }; //简单使用代码 Application* app = new Application(HelpHandler::EAPPLICATION_HELP_TOPIC); Dialog* dialog = new Dialog(app, HelpHandler::EPRINT_HELP_TOPIC); Button* button = new Button(dialog, HelpHandler::ECONFIRM_HELP_TOPIC); //想要显示谁的help,只需要如下调用HandleHelp即可 button->HandleHelp();
看了代码应该就很清晰了。职责链模式常与Composite组合模式一起使用。