實(shí)現(xiàn)狀態(tài)機(jī)有多種模式,其中最靈活而強(qiáng)大的方式是通過遷移表來實(shí)現(xiàn),該方式的缺點(diǎn)之一是需要編寫大量小塊代碼去支持遷移表。而在C#3.0中,可以以一種非常優(yōu)雅的方式實(shí)現(xiàn)。除了有限狀態(tài)機(jī)外,還有有限自動(dòng)機(jī),有限自動(dòng)機(jī)一般用于分析字符。usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;namespaceStateMachine{ classPRogram { staticvoidMain(string[] args) { vardoor =newDoor(State.Open); while(true) { strings =Console.ReadLine(); Operationop =string.IsNullOrEmpty(s) ?Operation.Push :Operation.Pull; door.Process(op); } } } enumOperation { Push, Pull } enumState { Open, Closed } classDoor { publicStateState {get;set; } Dictionary<State,Dictionary<Operation,Action>> rule; publicDoor(Statestate) { this.State = state; rule =newDictionary<State,Dictionary<Operation,Action>>(); foreach(vareinEnum.GetValues(typeof(State))) { rule[(State)e] =newDictionary<Operation,Action>(); } InitOperationRule(); } voidInitOperationRule() { //正常操作 rule[State.Closed][Operation.Push] = () => {Console.WriteLine("門被推開了"); State =State.Open; }; rule[State.Open][Operation.Pull] = () => {Console.WriteLine("門被拉上了"); State =State.Closed; }; ////加入幾種特殊情況的處理 //rule[State.Closed][Operation.Pull] = () => Console.WriteLine("門是關(guān)上的,拉了也白拉"); //rule[State.Open][Operation.Push] = () => Console.WriteLine("門是開的,不用推了,直接進(jìn)去吧"); } publicvoidProcess(Operationop) { try { rule[State][op](); } catch(KeyNotFoundException) { Console.WriteLine(string.Format("門在{0}狀態(tài)下不允許{1}操作", State, op)); } } }}從代碼中可以看到,通過lambda表達(dá)式,可以簡(jiǎn)化遷移表的構(gòu)造,并且更加直觀。通過遷移表構(gòu)造狀態(tài)機(jī)的一種不足在于查詢速度,在本例中每個(gè)操作都要進(jìn)行兩次查詢才能進(jìn)行狀態(tài)轉(zhuǎn)換操作。如果狀態(tài)較多則非常費(fèi)時(shí),這里我把它改進(jìn)了一下,使得每次操作只需要查詢一次即可。 classDoorPlus { Statestate; publicStateState { get{returnstate; } set { if(state !=value) currentOpRule = rule[value]; state =value; } } Dictionary<Operation,Action> currentOpRule; Dictionary<State,Dictionary<Operation,Action>> rule; publicDoorPlus(Statestate) { this.State = state; rule =newDictionary<State,Dictionary<Operation,Action>>(); foreach(vareinEnum.GetValues(typeof(State))) { rule[(State)e] =newDictionary<Operation,Action>(); } currentOpRule = rule[State]; InitOperationRule(); } voidInitOperationRule() { //正常操作 rule[State.Closed][Operation.Push] = () => {Console.WriteLine("門被推開了"); State =State.Open; }; rule[State.Open][Operation.Pull] = () => {Console.WriteLine("門被拉上了"); State =State.Closed; }; ////加入幾種特殊情況的處理 //rule[State.Closed][Operation.Pull] = () => Console.WriteLine("門是關(guān)上的,拉了也白拉"); //rule[State.Open][Operation.Push] = () => Console.WriteLine("門是開的,不用推了,直接進(jìn)去吧"); } publicvoidProcess(Operationop) { try { currentOpRule[op](); } catch(KeyNotFoundException) { Console.WriteLine(string.Format("門在{0}狀態(tài)下不允許{1}操作", State, op)); } } }
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注