您的位置:首页 > 移动开发 > Unity3D

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加减乘除

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 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

责任链模式代码结构

//-------------------------------------------------------------------------------------
//  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);
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  设计模式 unity
相关文章推荐