C# 3.0下有限状态机的一种优雅的实现
C# 3.0下有限狀態機的一種優雅的實現
實現狀態機有多種模式,其中最靈活而強大的方式是通過遷移表來實現,該方式的缺點之一是需要編寫大量小塊代碼去支持遷移表。而在C#3.0中,可以以一種非常優雅的方式實現。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace StateMachine
{
????class Program
????{
????????static void Main(string[] args)
????????{
????????????var door = new Door(State.Open);
????????????while (true)
????????????{
????????????????string s = Console.ReadLine();
????????????????Operation op = string.IsNullOrEmpty(s) ? Operation.Push : Operation.Pull;
????????????????door.Process(op);
????????????}
????????}
????}
????enum Operation
????{
????????Push, Pull
????}
????enum State
????{
????????Open, Closed
????}
????class Door
????{
????????public State State { get; set; }
????????Dictionary<State, Dictionary<Operation, Action>> rule;
????????public Door(State state)
????????{
????????????this.State = state;
????????????rule = new Dictionary<State, Dictionary<Operation, Action>>();
????????????foreach (var e in Enum.GetValues(typeof(State)))
????????????{
????????????????rule[(State)e] = new Dictionary<Operation, Action>();
????????????}
????????????InitOperationRule();
????????}
????????void InitOperationRule()
????????{
????????????//正常操作
????????????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("門是關上的,拉了也白拉");
????????????//rule[State.Open][Operation.Push] = () => Console.WriteLine("門是開的,不用推了,直接進去吧");
????????}
????????public void Process(Operation op)
????????{
????????????try
????????????{
????????????????rule[State][op]();
????????????}
????????????catch (KeyNotFoundException)
????????????{
????????????????Console.WriteLine(string.Format("門在{0}狀態下不允許{1}操作", State, op));
????????????}
????????????
????????}
????}
}
從代碼中可以看到,通過lambda表達式,可以簡化遷移表的構造,并且更加直觀。
通過遷移表構造狀態機的一種不足在于查詢速度,在本例中每個操作都要進行兩次查詢才能進行狀態轉換操作。如果狀態較多則非常費時,這里我把它改進了一下,使得每次操作只需要查詢一次即可。
????class DoorPlus
????{
????????State state;
????????public State State
????????{
????????????get { return state; }
????????????set
????????????{
????????????????if (state != value)
????????????????????currentOpRule = rule[value];
????????????????state = value;
????????????}
????????}
????????Dictionary<Operation, Action> currentOpRule;
????????Dictionary<State, Dictionary<Operation, Action>> rule;
????????public DoorPlus(State state)
????????{
????????????this.State = state;
????????????rule = new Dictionary<State, Dictionary<Operation, Action>>();
????????????foreach (var e in Enum.GetValues(typeof(State)))
????????????{
????????????????rule[(State)e] = new Dictionary<Operation, Action>();
????????????}
????????????currentOpRule = rule[State];
????????????InitOperationRule();
????????}
????????void InitOperationRule()
????????{
????????????//正常操作
????????????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("門是關上的,拉了也白拉");
????????????//rule[State.Open][Operation.Push] = () => Console.WriteLine("門是開的,不用推了,直接進去吧");
????????}
????????public void Process(Operation op)
????????{
????????????try
????????????{
????????????????currentOpRule[op]();
????????????}
????????????catch (KeyNotFoundException)
????????????{
????????????????Console.WriteLine(string.Format("門在{0}狀態下不允許{1}操作", State, op));
????????????}
????????}
????}
總結
以上是生活随笔為你收集整理的C# 3.0下有限状态机的一种优雅的实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android之View和Surface
- 下一篇: 远程桌面连接超出最大连接数的问题