2015年6月23日 星期二

以State Pattern取代巢狀迴圈

.NET   Design Pattern  

背景

專案中需要判斷三次邏輯後,決定程式要執行的邏輯。
因此採用Design Pattern : State 來取代這些槽狀迴圈。

環境

l   Windows 7 pro
l   Visual Studio 2012 (C#)


實作


State : Initiate

l   所有狀態的列舉型別
public enum TriggerActValStateEnum
    {
        Null = 1,
        IamProfitAivCashIncludingLoss,
        IamProfitAivCashPure,
        IamProfitAivCntIncludingLoss,
        IamProfitAivCntPure,
        IamProfitAivRateIncludingLoss,
        IamProfitAivRatePure
    }


l   State interface
/// <summary>
///狀態interface
/// </summary>
public interface ITriggerActValState
    {
        /// <summary>
        /// Trigger統計的方式
        /// </summary>
        TriggerActValStateEnum TriggerActValStateEnum { get; set; }
        /// <summary>
        ///  執行目前的狀態要做的事情,並設定下一個狀態
        /// </summary>
        void SetNewState(TriggerActValContext _context);
    }


l   Create update codes for the Model

/// <summary>
/// abstract class for 狀態
/// </summary>
public abstract class TriggerActValState : ITriggerActValState
    {
        public TriggerActValStateEnum TriggerActValStateEnum { get; set; }
        public abstract void SetNewState(TriggerActValContext context);
    }


l   Context for state pattern

/// <summary>
/// Context for state pattern
/// </summary>
    public class TriggerActValContext:IDisposable
    {
        /// <summary>
        /// 目前的狀態類別
        /// </summary>
        public ITriggerActValState State {get;set;}

        /// <summary>
        /// 條件一
        /// </summary>
        public TriggerTypeEnum TriggerType { get; set; }
        /// <summary>
        /// 條件二
        /// </summary>
        public AIVTypeEnum AivType { get; set; }
        /// <summary>
        /// 條件三
        /// </summary>
        public bool IsIncludingOpposite { get; set; }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="triggerType">條件一</param>
        /// <param name="aivType">條件二</param>
        /// <param name="isIncludingOpposite">條件三</param>
        public TriggerActValContext(
            TriggerTypeEnum triggerType,
            AIVTypeEnum aivType,
            bool isIncludingOpposite)
        {
            this.TriggerType = triggerType;
            this.AivType = aivType;
            this.IsIncludingOpposite = isIncludingOpposite;

            switch(triggerType) //由判斷條件一決定下一個狀態
            {
                case TriggerTypeEnum.Profit:
                    this.State = new IamProfitTrigger();
                    break;
                case TriggerTypeEnum.Loss:
                    this.State = new IamLossTrigger();
                    break;
                default:
                    break;
            }

        }

        /// <summary>
        /// 執行State裡面的動作
        /// </summary>
        public void EnableState()
        {
            this.State.SetNewState(this);
        }

    }



State : Implement Every State

l   判斷條件二決定下一個狀態
public class IamProfitTrigger : TriggerActValState
    {
       
        public override void SetNewState(TriggerActValContext context)
        {
//設定目前狀態
            base.TriggerActValStateEnum = TriggerActValStateEnum.Null;
            //設定下一個工作
            switch(context.AivType)
            {
                case AIVTypeEnum.Cash:
                    context.State = new IamProfitAivCash();
                    break;
                case AIVTypeEnum.Counter:
                    context.State = new IamProfitAivCnt();
                    break;
                case AIVTypeEnum.Rate:
                    context.State = new IamProfitAivRate();
                    break;
                default:
                    break;
            }
            context.EnableState();
           
        }
    }

l   判斷條件三決定下一個狀態
public class IamProfitAivCnt : TriggerActValState
    {
        public override void SetNewState(TriggerActValContext context)
        {
            //設定目前狀態
            base.TriggerActValStateEnum = TriggerActValStateEnum.Null;

            //設定下一個工作
            if (context.IsIncludingOpposite)
            {
                context.State = new IamProfitAivCntIncludingLoss();
            }
            else
            {
                context.State = new IamProfitAivCntPure();
            }
            context.EnableState();

        }
    }

l   決定最後的狀態
public class IamProfitAivCashIncludingLoss : TriggerActValState
    {
        public override void SetNewState(TriggerActValContext context)
        {
            //設定目前狀態
            base.TriggerActValStateEnum = TriggerActValStateEnum.IamProfitAivCashIncludingLoss;
        }
    }



主程式

using (var context = new TriggerActValContext(triggerType, aivType, isIncludingLoss))
{
context.EnableState();

//依據最後的狀態,決定要執行的邏輯
    switch (context.State.TriggerActValStateEnum)
    {
case TriggerActValStateEnum.IamProfitAivCntPure:
         //執行邏輯
             break;
         case TriggerActValStateEnum.IamProfitAivCashPure:
         //執行邏輯
             break;
         //…
         default:
             break;
     }
}


Reference



沒有留言:

張貼留言