Design Pattern - Chain of Responsibility(C#)
阿新 • • 發佈:2018-11-02
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
Definition
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
Participants
The classes and/or objects participating in this pattern are:
- Handler (Approver)
- Defines an interface for handling the requests
- (optional) Implements the successor link
- ConcreteHandler (Director, VicePresident, President)
- Handles requests it is responsible for
- Can access its successor
- If the ConcreteHandler can handle the request, it does so; otherwise it forwards the request to its successor
- Client (ChainApp)
- Initiates the request to a ConcreteHandler object on the chain
Sample Code in C#
This structural code demonstrates the Chain of Responsibility pattern in which several linked objects (the Chain) are offered the opportunity to respond to a request or hand it off to the object next in line.
// --------------------------------------------------------------------------------------------------------------------// <copyright company="Chimomo's Company" file="Program.cs">// Respect the work.// </copyright>// <summary>// Structural Chain of Responsibility Design Pattern.// </summary>// --------------------------------------------------------------------------------------------------------------------namespace CSharpLearning{ using System; /// <summary> /// Startup class for Structural Chain of Responsibility Design Pattern. /// </summary> internal static class Program { #region Methods /// <summary> /// Entry point into console application. /// </summary> private static void Main() { // 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); } } #endregion } /// <summary> /// The 'Handler' abstract class /// </summary> internal abstract class Handler { #region Fields /// <summary> /// The successor. /// </summary> protected Handler Successor; #endregion #region Public Methods and Operators /// <summary> /// The handle request. /// </summary> /// <param name="request"> /// The request. /// </param> public abstract void HandleRequest(int request); /// <summary> /// The set successor. /// </summary> /// <param name="successor"> /// The successor. /// </param> public void SetSuccessor(Handler successor) { this.Successor = successor; } #endregion } /// <summary> /// The 'ConcreteHandler1' class /// </summary> internal class ConcreteHandler1 : Handler { #region Public Methods and Operators /// <summary> /// The handle request. /// </summary> /// <param name="request"> /// The request. /// </param> public override void HandleRequest(int request) { if (request >= 0 && request < 10) { Console.WriteLine("{0} handled request {1}", this.GetType().Name, request); } else if (this.Successor != null) { this.Successor.HandleRequest(request); } } #endregion } /// <summary> /// The 'ConcreteHandler2' class /// </summary> internal class ConcreteHandler2 : Handler { #region Public Methods and Operators /// <summary> /// The handle request. /// </summary> /// <param name="request"> /// The request. /// </param> public override void HandleRequest(int request) { if (request >= 10 && request < 20) { Console.WriteLine("{0} handled request {1}", this.GetType().Name, request); } else if (this.Successor != null) { this.Successor.HandleRequest(request); } } #endregion } /// <summary> /// The 'ConcreteHandler3' class /// </summary> internal class ConcreteHandler3 : Handler { #region Public Methods and Operators /// <summary> /// The handle request. /// </summary> /// <param name="request"> /// The request. /// </param> public override void HandleRequest(int request) { if (request >= 20 && request < 30) { Console.WriteLine("{0} handled request {1}", this.GetType().Name, request); } else if (this.Successor != null) { this.Successor.HandleRequest(request); } } #endregion }}// Output:/*ConcreteHandler1 handled request 2ConcreteHandler1 handled request 5ConcreteHandler2 handled request 14ConcreteHandler3 handled request 22ConcreteHandler2 handled request 18ConcreteHandler1 handled request 3ConcreteHandler3 handled request 27ConcreteHandler3 handled request 20*/
This real-world code demonstrates the Chain of Responsibility pattern in which several linked managers and executives can respond to a purchase request or hand it off to a superior. Each position has can its own set of rules which orders they can approve.
// --------------------------------------------------------------------------------------------------------------------// <copyright company="Chimomo's Company" file="Program.cs">// Respect the work.// </copyright>// <summary>// Real-World Chain of Responsibility Design Pattern.// </summary>// --------------------------------------------------------------------------------------------------------------------namespace CSharpLearning{ using System; /// <summary> /// Startup class for Real-World Chain of Responsibility Design Pattern. /// </summary> internal static class Program { #region Methods /// <summary> /// Entry point into console application. /// </summary> private 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 var 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); } #endregion } /// <summary> /// The 'Handler' abstract class /// </summary> internal abstract class Approver { #region Fields /// <summary> /// The successor. /// </summary> protected Approver Successor; #endregion #region Public Methods and Operators /// <summary> /// The process request. /// </summary> /// <param name="purchase"> /// The purchase. /// </param> public abstract void ProcessRequest(Purchase purchase); /// <summary> /// The set successor. /// </summary> /// <param name="successor"> /// The successor. /// </param> public void SetSuccessor(Approver successor) { this.Successor = successor; } #endregion } /// <summary> /// The 'ConcreteHandler' class /// </summary> internal class Director : Approver { #region Public Methods and Operators /// <summary> /// The process request. /// </summary> /// <param name="purchase"> /// The purchase. /// </param> public override void ProcessRequest(Purchase purchase) { if (purchase.Amount < 10000.0) { Console.WriteLine("{0} approved request# {1}", this.GetType().Name, purchase.Number); } else if (this.Successor != null) { this.Successor.ProcessRequest(purchase); } } #endregion } /// <summary> /// The 'ConcreteHandler' class /// </summary> internal class VicePresident : Approver { #region Public Methods and Operators /// <summary> /// The process request. /// </summary> /// <param name="purchase"> /// The purchase. /// </param> public override void ProcessRequest(Purchase purchase) { if (purchase.Amount < 25000.0) { Console.WriteLine("{0} approved request# {1}", this.GetType().Name, purchase.Number); } else if (this.Successor != null) { this.Successor.ProcessRequest(purchase); } } #endregion } /// <summary> /// The 'ConcreteHandler' class /// </summary> internal class President : Approver { #region Public Methods and Operators /// <summary> /// The process request. /// </summary> /// <param name="purchase"> /// The purchase. /// </param> 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); } } #endregion } /// <summary> /// Class holding request details /// </summary> internal class Purchase { // Constructor #region Constructors and Destructors /// <summary> /// Initializes a new instance of the <see cref="Purchase"/> class. /// </summary> /// <param name="number"> /// The number. /// </param> /// <param name="amount"> /// The amount. /// </param> /// <param name="purpose"> /// The purpose. /// </param> public Purchase(int number, double amount, string purpose) { this.Number = number; this.Amount = amount; this.Purpose = purpose; } #endregion // Gets or sets purchase amount #region Public Properties /// <summary> /// Gets or sets the amount. /// </summary> public double Amount { get; set; } /// <summary> /// Gets or sets the number. /// </summary> public int Number { get; set; } // Gets or sets purchase purpose /// <summary> /// Gets or sets the purpose. /// </summary> public string Purpose { get; set; } #endregion }}// Output:/*Director Larry approved request# 2034President Tammy approved request# 2035Request# 2036 requires an executive meeting!*/