设计模式(13) 对象行为型模式和职责链模式(一)

2014-11-24 02:38:21 · 作者: · 浏览: 1
问题聚焦: 行为模式,将你的注意力从控制流转移到对象间的联系通信方式上来。 本节所介绍的职责链,是典型的松耦合设计模式。 职责链模式可以相应多个请求接受者,选择其中最合适的处理者。


行为模式: 定义:算法和对象间职责的分配,不仅描述对象或类的模式,还描述它们之间的通信模式。 使用继承机制:使用继承机制在类间分派行为。如Tempalte Method和Interpreter。 使用对象复合:一些行为对象模式描述了一组对等的对象怎样相互协作以完成其中任一个对象都无法单独完成的任务。其要注意的问题是如何低耦合又保持相互的了解。如Mediator模式提供的松耦合所需的间接性。 职责链(Chain of Responsibility)通过一条候选对象链式向一个对象发送请求。 观察者模式(Oberserver)定义并保持对象间的依赖关系。 其他的行为对象模式常将行为封装在一个对象中并将请求指派给它。
职责链(Chain Of Responsibility) 意图: 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。 将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
动机: 依然以一个实际的例子说明该模式的设计出发点。 Demo: 考虑一个图形用户界面中的帮助机制设计 需求:用户在界面的任一部分上点击就可以得到帮助信息,所提供的帮助依赖于点击的是界面的哪一部分以及其上下文。 如果对那一部分界面没有特定的帮助信息,那么帮助系统应该显示一个关于当前上下文的较一般的帮助信息。比如,整个对话框的帮助信息。 思路:从特殊到普遍的顺序组织帮助信息,有一个对象专门负责选择帮助请求。 挑战:提交帮助请求的对象并不明确知道谁是最终提供帮助的对象。我们要做的是将提交帮助请求的对象与可能提供帮助信息的对象解耦和。 给多个对象处理一个请求的机会,挑选最适合的处理者,从而解耦发送者和接受者。该请求将按对象链传递,知道一个合适的请求接受者对它作出反应。 如下图所示: \ \ 在PrintButton和OKButton接收到的请求并不直接处理,而是沿转发链向下转发至PrintDialog,一直到Application,Application处理它或忽略它。 效果就是,提交请求的客户不直接引用最终相应它的对象。 实现:要沿链转发请求,并保证接收者为隐式的(implicit),每个链上的对象都有一致的处理请求和访问链上后继者的接口。 设计:HelpHandler类,作为所有候选对象类的父类,用HelpHandler定义的接口处理帮助请求,或者下发请求。 HandleHelp操作缺省的是将请求转发给后继,子类可重定义这一操作以在适当的情况下提供帮助;否则它们可使用缺省实现转发该请求。 \ \

适用性: 以下情况使用Responsibility链:
  • 有多个的对象可以处理一个请求,哪个对象处理该请求,在运行时刻自动确定。
  • 你想在不明确指定接受者的情况下,向多个对象中的一个,提交一个请求。
  • 可处理一个请求的对象集合应被动态指定。 结构: \
    \ 一个典型的对象结构可能如下图所示: \
    \ 参与者:
    • Handler(HelpHandler):
      • 定义一个处理请求的接口
      • 实现后继
      • Concretehandler(PrintButton):
        • 处理它负责的请求
        • 可访问它的后继者
        • 如果可处理该请求,就处理;否则将该请求转发给它的后继者
        • Client:向链上的具体处理者对象提交请求 协作: 当客户提交一个请求时,请求沿链传递直至有一个ConcreteHandler对象负责处理它。
          效果: 优点和缺点 降低耦合度:请求提交者无需知道哪一个对象处理请求;请求接受者不需要知道链的存在,它只需要知道它的后继是谁。增强了给对象指派职责的灵活度不保证被接受:当请求到达链尾仍没有被处理时,就得不到处理。


          实现: 下面是在职责链模式中要考虑的实现问题:
          • 实现后继者链(接受请求者组成的处理请求链):
            • 定义新的链接
            • 使用已有的链接:在组合模式(CompZ http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vc2l0ZaOp1tDP6s+4tdjM1sLbwcvKyrrP1/e687zM1d/BtLXEveG5uQo8bGk+way907rzvMzV36O6yOe5+8O709DSu7j2v8nKudPDtcTS/dPDtqjS5dK7uPbBtKOsxMfDtEhhbmRsZXKyu732tqjS5bjDx+vH87XEvdO/2qOszaizo9Kyzqy7pLrzvMzBtL3ToaPV4sqxo6xDb25jcmV0ZWhhbmRsZXLX08DgttS4w8frx/Oyu7jQ0MvIpMqxo6y9+NDQzt7M9bz+16q3oqGjPGxpPrHtyr7H68fzo7rI/dbWt73KvbHtyr7H68fzCgq88rWltdijrNOyseDC67LZ1/e199PDo6zIsbXjo6zWu8Tc16q3orao0uW1xLnMtqi1xNK71+nH68fzyrnTw7SmwO26r8r9o6y908rc0ru49sfrx/PC66GjyrnTw7bAwaK1xMfrx/O21M/zx+vH87LOyv2hoyAgIAoKCrT6wuvKvsD9o7oKz8LD5tLUx7DD5sv5yva1xNTaz9+w79b6z7XNs6OswLTR3cq+1rDU8MG0ysfI57rOtKbA7cfrx/O1xKGjCsDgyei2qKO6CkhlbHBIYW5kbGVywOC2qNLlwcu0psDtsO/W+sfrx/O1xL3Tv9qhowrWsNTwo7rOrLuk0ru49rDv1vrW98zio7uxo7PWttSw79b6tKbA7bbUz/PBtNbQtcS687zM1d+1xNL908MKudi8/LLZ1/ejukhhbmxkZUhlbHCjrL/JsbvX08Dg1ti2qNLlo7tIYXNIZWxwuKjW+rLZ1/ejrNPD09q87LLpyse38dPQ0ru49s/gudi1xLDv1vrW98zioaMKPHByZSBjbGFzcz0="brush:java;">typedef int Topic; const Topic NO_HELP_TOPIC = -1; class HelpHandler { public: HelpHanlder(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) {} HelpHandler::HandlerHelp () { if (_successor != 0) { _successor->HandleHelp(); } } Widget抽象类:所有窗口组件的父类
              class Wi