1.1设计模式在Unity中应用—Behavioral Pattern— Chain of Responsibility Pattern 责任链模式

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

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值