定义:使用多个类而不是一个去传递请求,可以很大程度上降低请求的发出者与接受者之间的耦合。多个类成链式,去接受请求,在请求的接受者接受之前传递请求。
UML图:
类:
Handler: 定义处理请求的接口
ConcreteHandler:1:处理请求
2:获取下一个链接者
3:如果这个类可以处理请求,处理;否则传递给下一个链接者。
Client: 初始化请求,发送请求。
用C#写的小例子:
using System; namespace DoFactory.GangOfFour.Chain.Structural { /// <summary> /// 责任链设计模式 /// </summary> class MainApp { /// <summary> /// 程序入口点 /// </summary> static void Main() { // 新建责任链 Handler h1 = new ConcreteHandler1(); Handler h2 = new ConcreteHandler2(); Handler h3 = new ConcreteHandler3(); h1.SetSuccessor(h2); h2.SetSuccessor(h3); // 初始化请求 int[] requests = { 2, 5, 14, 22, 18, 3, 27, 20 }; foreach (int request in requests) { h1.HandleRequest(request); } // 等待 Console.ReadKey(); } } /// <summary> /// 'Handler'接口或抽象类 /// </summary> abstract class Handler { protected Handler successor; public void SetSuccessor(Handler successor) { this.successor = successor; } public abstract void HandleRequest(int request); } /// <summary> ///'ConcreteHandler1' 类 /// </summary> class ConcreteHandler1 : Handler { public override void HandleRequest(int request) { if (request >= 0 && request < 10) { Console.WriteLine("{0} handled request {1}", this.GetType().Name, request); } else if (successor != null) { successor.HandleRequest(request); } } } /// <summary> /// The 'ConcreteHandler2' class /// </summary> class ConcreteHandler2 : Handler { public override void HandleRequest(int request) { if (request >= 10 && request < 20) { Console.WriteLine("{0} handled request {1}", this.GetType().Name, request); } else if (successor != null) { successor.HandleRequest(request); } } } /// <summary> /// The 'ConcreteHandler3' class /// </summary> class ConcreteHandler3 : Handler { public override void HandleRequest(int request) { if (request >= 20 && request < 30) { Console.WriteLine("{0} handled request {1}", this.GetType().Name, request); } else if (successor != null) { successor.HandleRequest(request); } } } }
现实点的例子
using System; namespace DoFactory.GangOfFour.Chain.RealWorld { /// <summary> /// MainApp startup class for Real-World /// Chain of Responsibility Design Pattern. /// </summary> class MainApp { /// <summary> /// Entry point into console application. /// </summary> static void Main() { // Setup Chain of Responsibility Approver larry = new Director(); Approver sam = new VicePresident(); Approver tammy = new President(); larry.SetSuccessor(sam); sam.SetSuccessor(tammy); // Generate and process purchase requests Purchase p = new Purchase(2034, 350.00, "Assets"); larry.ProcessRequest(p); p = new Purchase(2035, 32590.10, "Project X"); larry.ProcessRequest(p); p = new Purchase(2036, 122100.00, "Project Y"); larry.ProcessRequest(p); // Wait for user Console.ReadKey(); } } /// <summary> /// The 'Handler' abstract class /// </summary> abstract class Approver { protected Approver successor; public void SetSuccessor(Approver successor) { this.successor = successor; } public abstract void ProcessRequest(Purchase purchase); } /// <summary> /// The 'ConcreteHandler' class /// </summary> class Director : Approver { public override void ProcessRequest(Purchase purchase) { if (purchase.Amount < 10000.0) { Console.WriteLine("{0} approved request# {1}", this.GetType().Name, purchase.Number); } else if (successor != null) { successor.ProcessRequest(purchase); } } } /// <summary> /// The 'ConcreteHandler' class /// </summary> class VicePresident : Approver { public override void ProcessRequest(Purchase purchase) { if (purchase.Amount < 25000.0) { Console.WriteLine("{0} approved request# {1}", this.GetType().Name, purchase.Number); } else if (successor != null) { successor.ProcessRequest(purchase); } } } /// <summary> /// The 'ConcreteHandler' class /// </summary> class President : Approver { public override void ProcessRequest(Purchase purchase) { if (purchase.Amount < 100000.0) { Console.WriteLine("{0} approved request# {1}", this.GetType().Name, purchase.Number); } else { Console.WriteLine( "Request# {0} requires an executive meeting!", purchase.Number); } } } /// <summary> /// Class holding request details /// </summary> class Purchase { private int _number; private double _amount; private string _purpose; // Constructor public Purchase(int number, double amount, string purpose) { this._number = number; this._amount = amount; this._purpose = purpose; } // Gets or sets purchase number public int Number { get { return _number; } set { _number = value; } } // Gets or sets purchase amount public double Amount { get { return _amount; } set { _amount = value; } } // Gets or sets purchase purpose public string Purpose { get { return _purpose; } set { _purpose = value; } } } }