职责链模式
模式定义
职责链模式使多个对象有机会处理请求,从而避免请求的发送者与接收者之间的耦合关系。将这些对象连成一个链条,沿着链条传递该请求,直到有一个对象处理它为止。 在GOF95中该模式被分类为行为型模式。
模式结构与说明
- Handler:定义职责的接口,通常包含了处理请求的方法。successor引用链条中下一个Handler
- ConcreteHandler:具体职责类,该类实现对其职责范围内的请求的处理,如果不处理,就转发给successor
- Client:职责链的客户端,向链上的具体对象提交请求,让职责链负责处理
职责链模式的优点:
- 请求者和接收者解耦:请求者不知道是谁处理了请求
- 职责链的动态组合和排序
职责链模式的缺点:
- 可能会产生很多细粒度的Handler
- 不能保证请求被Handler处理,由于链条配置的不正确,可能无任何Handler支持某个请求
应用举例
这是一个简单的帮助系统的例子,如果按钮包含帮助信息的话,就显示当前按钮的帮助,否则按钮类控件的通用信息,如果通用信息也没有的话,则显提示用户“没有相关的帮助”:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
class HelpeRequest( object ): @property def target( self ): return self.target def __init__( self, target ): self.target = target class HelpHandler( object ): @property def __init__( self, successor ): self.successor = successor def successor( self ): return self.successor def hasHelpContent( self ): return False def handleHelp( self, request ): return self.successor.handleHelp( self, request ) class ButtonHelperHandler( HelpHandler ): def handleHelp( self, request ): if self.hasHelpContent( request.target ): print 'Button Help content.' else: HelpHandler.handleHelp( self, request ) class WidgetHelperHandler( HelpHandler ): def handleHelp( self, request ): if self.hasHelpContent( request.target ): print 'Widget Help content.' else: HelpHandler.handleHelp( self, request ) class DefaultHelperHandler( HelpHandler ): def handleHelp( self, request ): print 'No help available.' if __name__ == '__main__': # 装配责任链 dhh = DefaultHelperHandler( None ) whh = WidgetHelperHandler( dhh ) bhh = ButtonHelperHandler( whh ) # 使用责任链 req = HelpeRequest( 'A button' ) bhh.handleHelp( req ) |
经典应用
Servlet的过滤器机制
Sevlet框架中的Filter机制是一种变形的职责链模式。在Servlet的设计中,职责链被具象化为一个接口FilterChain,在作为Handler角色的Filter则不再维护对Successor的引用。
在Tomcat的Servlet实现中,ApplicationFilterChain负责调用配置的第一个Filter,后者则可以决定自己处理,或者通过FilterChain.doFilter调用下一个Filter,例如:
1 2 3 4 5 6 7 |
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //进行各种处理,例如处理编码、处理身份验证 …… // 沿着链条传递请求 chain.doFilter(request, response); } |
模式演变
- 功能链:在标准的职责链中,一旦有Handler处理请求即结束,功能链允许多个Handler完成对请求的一部分处理,典型的例子是Servlet的过滤器机制
- 与组合模式联用:在必要的情况下,可以使用组合模式构建复杂的树形结构作为Handler的链条
- 与命令模式的相似点:两者都将请求者和接收者进行解耦
Leave a Reply