Design Pattern : State
作者: JB
State pattern使用的時機及範例,可以網路上很多文章。
作者: JB
State pattern使用的時機及範例,可以網路上很多文章。
主要是使用在有順序的事件上,可以免除if…else…或swith…case…的程式碼。
當然缺點就是要多一層去做State管理,以及多出多支對應的State class。
這邊會以實務上:依序做四次電文的傳送為範例。
每一次的電文傳送就是一種狀態(State)
當然缺點就是要多一層去做State管理,以及多出多支對應的State class。
這邊會以實務上:依序做四次電文的傳送為範例。
每一次的電文傳送就是一種狀態(State)
1.     
先定義四種電文的類型(State種類)
/// <summary>
   
/// 狀態種類
   
/// </summary>
   
public enum
StateKind
   
{
        /// <summary>
        /// 流程一
        /// </summary>
        A1,
        /// <summary>
        /// 流程二
        /// </summary>
        A2,
        /// <summary>
        /// 流程三
        /// </summary>
        T1,
        /// <summary>
        /// 流程四
        /// </summary>
        T2
   
}
2.      
定義State Pattern的核心類別:State 以及 Context
State : abstract class, 負責設定Context內容,以及設定某種狀態下需要執行的工作。
Context:負責存放目前執行的狀態:State,以及狀態種類:StateKind。
也負責設定哪個State為第一個要執行,和啟動目前狀態下需要執行的工作。
/// <summary>
/// State
/// </summary>
public abstract class State
{
/// <summary>
State : abstract class, 負責設定Context內容,以及設定某種狀態下需要執行的工作。
Context:負責存放目前執行的狀態:State,以及狀態種類:StateKind。
也負責設定哪個State為第一個要執行,和啟動目前狀態下需要執行的工作。
/// <summary>
/// State
/// </summary>
public abstract class State
{
/// <summary>
        /// 執行目前的狀態要做的事情(DoAction),並將目前狀態設定給下一個狀態
        /// </summary>
        /// <param
name="context">Context類別</param>
        /// <returns>訊息</returns>
        public abstract String
GetState(Context context);
        /// <summary>
        ///  執行目前的狀態要做的事情
        /// </summary>
        public abstract void
DoAction(Context _context);
   
}
/// <summary>
   
/// Context
   
/// </summary>
   
public class
Context
   
{
        //目前的狀態類別
        private
StateKind _stateKind;
        //存放狀態
        private
State _state;
        /// <summary>
        /// 建構
        /// </summary>
        public
Context()
        {
            this._state = new
A1_State(); 
//第一個要執行的State
        }
        /// <summary>
        /// 目前的狀態類別
        /// </summary>
        public StateKind StateKind
        {
            get
{ return this._stateKind;
}
            set
{ this._stateKind = value;
}
 
      }
        /// <summary>
        /// 存放狀態
        /// </summary>
        public State State
        {
            get
{ return this._state;
}
            set
{ this._state = value;
}
        }
        /// <summary>
        /// 執行State.GetState ... 
        /// </summary>
        /// <returns>訊息</returns>
        public String
GetState()
        {
            return _state.GetState(this);
        }
   
}
3.     
看到這邊,我們應該知道了,只要一直把State存放在Context,做完一個State時,告訴Context換下一個State再繼續做就可以了。
所以我們開始來實作四種State的程式碼… (這邊只列出一個)
/// <summary>
所以我們開始來實作四種State的程式碼… (這邊只列出一個)
/// <summary>
   
/// 狀態 : A1
   
/// </summary>
   
public class
A1_State:State
   
{
        /// <summary>
        /// 執行目前的狀態要做的事情(DoAction),並將目前狀態設定給下一個狀態
        /// </summary>
        /// <param
name="context"></param>
        /// <returns>訊息</returns>
        public override String
GetState(Context _context)
        {
            if
(_context.StateKind == StateKind.A1) 
            {
                //執行此狀態要做的事
                this.DoAction(_context);
                //設定下一個狀態為Auth2
               
_context.State = new A2_State();
               
_context.StateKind = StateKind.A2;
            }
            else
//非此State對應的StateKind
            {
                //...
            }
            return
"A1流程結束...";
        }
        /// <summary>
        /// 執行工作
        /// </summary>
        /// <param
name="_context">Context物件</param>
        public override void
DoAction(Context _context)
        {
           //Step3. 傳送電文
           Console.WriteLine("開始傳送A1電文");
  
     }
   
}
4.     
各自完成了A1、A2、T1、T2的覆寫State程式碼後,
接下來只要在主程式,宣告一個Context物件來啟動紀錄在其中的State動作即可。
請注意主程式並不用知道傳送電文的順序, 主程式只要知道總共有幾個電文要送就行了。
Context _context = new Context();
接下來只要在主程式,宣告一個Context物件來啟動紀錄在其中的State動作即可。
請注意主程式並不用知道傳送電文的順序, 主程式只要知道總共有幾個電文要送就行了。
Context _context = new Context();
String step1Msg = _context.GetState();
Console.WriteLine(step1Msg);
String step2Msg = _context.GetState();
Console.WriteLine(step2Msg);
String step3Msg = _context.GetState();
Console.WriteLine(step3Msg);
String step4Msg = _context.GetState();
Console.WriteLine(step4Msg);
執行結果 …………
開始傳送A1電文
A1流程結束...
開始傳送A2電文
A2流程結束...
開始傳送T1電文
T1流程結束...
開始傳送T2電文
T2流程結束...
 
沒有留言:
張貼留言