2017-01-23 73 views
0

我正在使用我的第一個asp.net mvc web應用程序。我有一種形式可以處於14種不同的狀態,根據當前狀態,轉換到其他狀態是或不可能的。每個當前狀態下平均有3-5個可能的下一個狀態。狀態機 - 嵌入式開關

我現在需要做的是在某些狀態轉換期間觸發動作。根據初始狀態和最終狀態,會觸發一些操作(例如發送電子郵件)。

我用switch語句開始了這一點:

switch ((int)currentState) 
     { 
      //Initial 
      case -1: 
       { 
        switch ((int)nextState) 
        { 
         //Next state: Inv. is waiting 
         case 1: 
          { 
           //Send email to x 
           emailHelper.Send(x,msg) 
           //Send email to Y 
           emailHelper.Send(y,anotherMsg) 

          } 
         case 2: 
          { 
           doSomethingelse() 
          } 
          break; 
        } 
        break; 
       } 
      //Inv is waiting 
      case 1: 
       { 
        switch ((int)nextState) 
        { 
         ... 
        } 
       } 
    ... 

我覺得這個解決方案將工作對我很好,但我想知道如果我可以用的東西better..Any建議?

+0

我更喜歡爲每個實際狀態設置一個'State'基類或'IState'接口和一個派生類。像第一個圖[這裏](https://www.codeproject.com/Articles/509234/The-State-Design-Pattern-vs-State-Machine)。 – itsme86

+0

但我需要觸發的動作是基於狀態轉換而不是實際狀態 –

+0

我不明白爲什麼狀態設計模式在這種情況下不起作用。閱讀關於'ConcreteState'及其職責的文章部分。 – itsme86

回答

1

(僞代碼)

class StateHandler 
{ 
    int CurrentState; 
    int NextState; 
    Action MyAction; 

    public void Eval(int currentState, int nextState) 
    { 
     if(currentState == this.CurrentState && nextState == this.NextState) 
     { 
      this.MyAction(); 
     } 
    } 
} 

創建列表,並與所有已知的狀態轉換填充它。然後迭代列表並在每個項目上調用Eval()。

List<StateHandler> handlers = new List<StateHandler>(); 
handlers.Add(new StateHandler() 
{ 
    currentState = 0, 
    nextState = 1, 
    () => doSomeWork() 
} 
handlers.Add(new StateHandler() 
{ 
    currentState = 3, 
    nextState = 4, 
    () => doSomeOtherWork() 
} 
2

也許你可以使用數據結構來存儲狀態和轉換。例如,該狀態機可以是Dictionary<int, State>,其中作爲

struct State { 
    Dictionary<int, Action> transitions; 
} 

執行然後狀態轉變看起來像

var action = states[currentState].transitions[nextState]; 
action(); 
currentState = nextState; 

當然,這個解決方案可以更包封State可能是一樣簡單,並可以使用檢查是否存在過渡,但這是它的要點

2

如果性能完全不是問題,並且唯一感興趣的是緊湊代碼,請考慮

switch(string.Format(CultureInfo.InvariantCulture, "{0} {1}", currentState, nextState)) 
{ 
    case "-1 1": 
     //Send email to x 
     emailHelper.Send(x,msg); 
     //Send email to Y 
     emailHelper.Send(y,anotherMsg); 
     break; 
    case "-1 2": 
     doSomethingelse(); 
     break; 
    .... 
} 

您也可以等待C#7.0並使用其新形式的switch statement。就像這樣:

struct State 
{ 
    int Current; 
    int Next; 
} 

.... 

State s; 
switch (s) 
{ 
    case State x when (x.Current == -1 && x.Next == 1): 
     .... 
} 
+0

這是一個有趣的想法。 –