1.1设计模式在Unity中应用—Behavioral Pattern— Chain of Responsibility Pattern 责任链模式
2017-12-22 14:58
1021 查看
Definition
Participants
Handler Approver
ConcreteHandler Director VicePresident President
Client ChainApp
责任链模式代码结构
案例1公司账单报销
案例2加减乘除
使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。
(optional) implements the successor link
can access its successor
if the ConcreteHandler can handle the request, it does so; otherwise it forwards the request to its successor
Participants
Handler Approver
ConcreteHandler Director VicePresident President
Client ChainApp
责任链模式代码结构
案例1公司账单报销
案例2加减乘除
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 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 forcan 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责任链模式代码结构
//------------------------------------------------------------------------------------- // ChainOfResponsibilityStructure.cs //------------------------------------------------------------------------------------- using UnityEngine; using System.Collections; public class ChainOfResponsibilityStructure : MonoBehaviour { void Start() { // 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); } } } /// <summary> /// The 'Handler' abstract class /// </summary> abstract class Handler { protected Handler successor; public void SetSuccessor(Handler successor) { this.successor = successor; } public abstract void HandleRequest(int request); } /// <summary> /// The 'ConcreteHandler1' class /// </summary> class ConcreteHandler1 : Handler { public override void HandleRequest(int request) { if (request >= 0 && request < 10) { Debug.Log(this.GetType().Name + " handled request " + 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) { Debug.Log(this.GetType().Name + " handled request " + 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) { Debug.Log(this.GetType().Name+" handled request "+request); } else if (successor != null) { successor.HandleRequest(request); } } }
案例1:公司账单报销
//------------------------------------------------------------------------------------- // ChainOfResponsibilityExample1.cs //------------------------------------------------------------------------------------- //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 have its own set of rules which orders they can approve. //这个代码演示了几个链接的责任链模式的实际应用 //经理和主管可以回应购买请求或将其交给上级。 //每个职位都可以有自己的一套规则,他们可以批准这些规则。 using UnityEngine; namespace ChainOfResponsibilityExample1 { public class ChainOfResponsibilityExample1 : MonoBehaviour { void Start ( ) { // 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, "¥350车费报销"); larry.ProcessRequest(p); p = new Purchase(2035, 32590.10, "¥32590.10 设备采购"); larry.ProcessRequest(p); p = new Purchase(2036, 122100.00, "¥122100 投资建厂"); larry.ProcessRequest(p); } } /// <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) { Debug.Log(this.GetType().Name+" approved request# "+purchase.Number+purchase.Purpose); } 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) { Debug.Log(this.GetType().Name + " approved request# " + purchase.Number + purchase.Purpose); } 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) { Debug.Log(this.GetType().Name + " approved request# " + purchase.Number + purchase.Purpose); } else { Debug.Log("Request# "+purchase.Number+ "requires an executive meeting!" + purchase.Number + purchase.Purpose); } } } /// <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; } } } }
案例2:加减乘除
//------------------------------------------------------------------------------------- // ChainOfResponsibilityExample2.cs //------------------------------------------------------------------------------------- using UnityEngine; using System.Collections; public class ChainOfResponsibilityExample2 : MonoBehaviour { void Start ( ) { // create calculation objects that get chained to each other in a sec Chain calc1 = new AddNumbers(); Chain calc2 = new SubstractNumbers(); Chain calc3 = new DivideNumbers(); Chain calc4 = new MultiplyNumbers(); // now chain them to each other calc1.SetNextChain(calc2); calc2.SetNextChain(calc3); calc3.SetNextChain(calc4); // this is the request that will be passed to a chain object to let them figure out which calculation objects it the right for the request // the request is here the CalculationType enum we add. so we want this pair of numbers to be added Numbers myNumbers = new Numbers(3, 5, CalculationType.Add); calc1.Calculate(myNumbers); // another example: Numbers myOtherNumbers = new Numbers(6, 2, CalculationType.Multiply); calc1.Calculate(myOtherNumbers); // or pass it to some chain object inbetween which will not work in this case: Numbers myLastNumbers = new Numbers(12, 3, CalculationType.Substract); calc3.Calculate(myLastNumbers); } // just defining some types of calculation we want to implement // it is better than passing string values as requests because you don't risk any typos that way :) public enum CalculationType { Add, Substract, Divide, Multiply }; // We use this object as an example object to be passed to the calculation chain ;-) // to figure out what we want to do with it (which is stored in CalculationType/calculationWanted) public class Numbers { // some numbers: public int number1 { get; protected set; } public int number2 { get; protected set; } // here we store in this object what we want to do with it to let the chain figure out who is responsible for it ;-) public CalculationType calculationWanted { get; protected set; } // constructor: public Numbers(int num1, int num2, CalculationType calcWanted) { this.number1 = num1; this.number2 = num2; this.calculationWanted = calcWanted; } } // doesn't need to be called chain of course ;-) public interface Chain { void SetNextChain(Chain nextChain); // to be called when calulcation fails void Calculate(Numbers numbers); // try to calculate } public class AddNumbers : Chain { // each chain object stored a private nextInChain object, that gets called when the method calculate fails protected Chain nextInChain; public void SetNextChain(Chain nextChain) { this.nextInChain = nextChain; } public void Calculate(Numbers request) { if(request.calculationWanted == CalculationType.Add) { Debug.Log("Adding: " + request.number1 + " + " + request.number2 + " = " + (request.number1 + request.number2).ToString()); } else if(nextInChain != null) nextInChain.Calculate(request); b60e else Debug.Log ("Handling of request failed: " + request.calculationWanted); } } public class SubstractNumbers : Chain { protected Chain nextInChain; public void SetNextChain(Chain nextChain) { this.nextInChain = nextChain; } public void Calculate(Numbers request) { if(request.calculationWanted == CalculationType.Substract) { Debug.Log("Substracting: " + request.number1 + " - " + request.number2 + " = " + (request.number1 - request.number2).ToString()); } else if(nextInChain != null) nextInChain.Calculate(request); else Debug.Log ("Handling of request failed: " + request.calculationWanted); } } public class DivideNumbers : Chain { protected Chain nextInChain; public void SetNextChain(Chain nextChain) { this.nextInChain = nextChain; } public void Calculate(Numbers request) { if(request.calculationWanted == CalculationType.Divide) { Debug.Log("Dividing: " + request.number1 + " / " + request.number2 + " = " + (request.number1 / request.number2).ToString()); } else if(nextInChain != null) nextInChain.Calculate(request); else Debug.Log ("Handling of request failed: " + request.calculationWanted); } } public class MultiplyNumbers : Chain { protected Chain nextInChain; public void SetNextChain(Chain nextChain) { this.nextInChain = nextChain; } public void Calculate(Numbers request) { if(request.calculationWanted == CalculationType.Multiply) { Debug.Log("Multiplying: " + request.number1 + " * " + request.number2 + " = " + (request.number1 * request.number2).ToString()); } else if(nextInChain != null) nextInChain.Calculate(request); else Debug.Log ("Handling of request failed: " + request.calculationWanted); } } }
相关文章推荐
- 我所理解的设计模式(C++实现)——责任链模式(Chain Of Responsibility Pattern)
- 乐在其中设计模式(C#) - 责任链模式(Chain of Responsibility Pattern)
- 设计模式 - Chain of Responsibility Pattern(责任链模式)
- 24种设计模式--责任链模式【Chain ofResponsibility Pattern】
- 【设计模式】责任链模式(Chain of Responsibility Pattern)
- 设计模式(十四)-责任链模式(Chain of Responsibility Pattern)——推卸责任
- 我所理解的设计模式(C++实现)——责任链模式(Chain Of Responsibility Pattern)
- 如何让孩子爱上设计模式 ——22.责任链模式(Chain of Responsibility Pattern)
- 23种设计模式(22)_行为型_责任链模式(Chain of Responsibility Pattern)
- 极速理解设计模式系列:12.责任链模式(Chain of Responsibility Pattern)
- 二十四种设计模式:责任链模式(Chain of Responsibility Pattern)
- 极速理解设计模式系列:12.责任链模式(Chain of Responsibility Pattern)
- 我所理解的设计模式(C++实现)——责任链模式(Chain Of Responsibility Pattern)
- 23种设计模式--责任链模式-Chain of Responsibility Pattern
- 设计模式6--责任链模式(The chain of responsibility pattern)
- java设计模式——责任链模式(Chain of Responsibility Pattern)
- 设计模式【责任链模式Chain of Responsibility Pattern】
- 设计模式学习—责任链模式(Chain of Responsibility Design Pattern)
- 设计模式 - Chain of Responsibility Pattern(责任链模式)
- 设计模式 笔记 责任链模式 chain of responsibility