本文共 2294 字,大约阅读时间需要 7 分钟。
使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。
在职责链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,知道链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织链和分配职责。
纯的与不纯的职责链模式:
一个纯的职责链模式要求一个具体的处理这对象只能在两个行为中选择一个:一个是承担职责;二是把职责推给下家。不允许出现某一个具体处理这对象在承担了一部分职责后又把职责向下传的情况。
在一个纯的职责链模式里面,一个请求必须被某一个处理者对象所接受;在一个不纯的职责链模式里,一个请求可以最终不被任何接收端对象所接受。
示例:
抽象处理者(Handler): 定义一个处理请求的接口;如果需要,可以定义一个方法,用以设定和返回对下家的引用。
具体处理者(ConcreteHandler): 具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家;
Client: 向链上的具体处理者对象提交请求。
职责链模式并不创建职责链,职责链的创建必须由系统的其他部分创建出来。
职责链可以是一条线,一个树,也可以是一个环;如下,职责链是一个树结构的一部分:
// Chain of Responsibility pattern -- Structural example using System;// "Handler"abstract class Handler{ // Fields protected Handler successor; // Methods public void SetSuccessor( Handler successor ) { this.successor = successor; } abstract public void HandleRequest( int request );}// "ConcreteHandler1"class ConcreteHandler1 : Handler{ // Methods override public void HandleRequest( int request ) { if( request >= 0 && request < 10 ) Console.WriteLine("{0} handled request {1}", this, request ); else if( successor != null ) successor.HandleRequest( request ); }}// "ConcreteHandler2"class ConcreteHandler2 : Handler{ // Methods override public void HandleRequest( int request ) { if( request >= 10 && request < 20 ) Console.WriteLine("{0} handled request {1}", this, request ); else if( successor != null ) successor.HandleRequest( request ); }}// "ConcreteHandler3"class ConcreteHandler3 : Handler{ // Methods override public void HandleRequest( int request ) { if( request >= 20 && request < 30 ) Console.WriteLine("{0} handled request {1}", this, request ); else if( successor != null ) successor.HandleRequest( request ); }}////// Client test/// public class Client{ public static void Main( string[] args ) { // Setup Chain of Responsibility Handler h1 = new ConcreteHandler1(); Handler h2 = new ConcreteHandler2(); Handler h3 = new ConcreteHandler3(); h1.SetSuccessor(h2); h2.SetSuccessor(h3); // Generate and process request int[] requests = { 2, 5, 14, 22, 18, 3, 27, 20 }; foreach( int request in requests ) h1.HandleRequest( request ); }}