状态机示例代码

状态机示例代码_第1张图片
Interface

    interface IAction
    {
        bool CanExecute(object args);
        void Execute(object args);
    } 
     
    interface IState
    {
        string Id { get; }
        List<ITransition> Transions { get; }
        void Enter(object args);
        void Exit(object args);
        string Transit(string transionId, object args);
    }
    interface IStateMachine
    {
        IState CurrentState { get; }
        List<IState> States { get; }
        bool Transit(string transitionId, object args);
    }
    /// 
    /// from和to相同时,表示想执行相关的行为
    /// 
    interface ITransition
    {
        string Id { get; } // From->To的路径可能有多种,因此添加ID作以区分
        string From { get; }
        string To { get; }
        List<IAction> Actions { get; } //状态转换所需要执行的行为
        bool IsReadyToTransit(object args); //判断执行的Actions是否都可以执行,都可以执行时表示可以进行转换
    }    

Realize

    class Transition : ITransition
    {
        public string Id { get; }

        public string From { get; }

        public string To { get; }

        public List<IAction> Actions { get; }

        public Transition(string id, string from, string to, List<IAction> actions=null)
        {
            Id = id;
            From = from;
            To = to;
            Actions = actions;
        }

        public bool IsReadyToTransit(object args)
        {
            return null == Actions || Actions.TrueForAll(a => a.CanExecute(args));
        }
    }

    class State : IState, IEquatable<IState>
    {
        public string Id { get; }
        public IAction EnterAction { private get;set ; }

        public IAction ExitAction { private get;set ; }

        public List<ITransition> Transions { get; }

        public State(string id)
        {
            Id = id;
            Transions = new List<ITransition>();
        }

        public virtual void Enter(object args)
        {
            Global.Log($"enter state: {Id}");
            EnterAction?.Execute(args);
        }

        public virtual void Exit(object args)
        {
            Global.Log($"exit state: {Id}");
            ExitAction?.Execute(args);
        }

        public string Transit(string transionId, object args)
        {
            var transition = Transions?.FirstOrDefault(t => t.Id == transionId);
            if (null == transition)
            {
                Global.LogWarning($"State:{Id} can not find any transition with Id: {transionId}");
                return null;
            }

            if (!transition.IsReadyToTransit(args))
            {
                Global.LogWarning($"transition:{transionId} is not ready to executed!");
                return null;
            }

            Exit(args);

            //run each action of transition
            transition.Actions?.ForEach(a => a.Execute(args));

            return transition.To;
        }

        public bool Equals(IState other)
        {
            return other?.Id == Id;
        }

        public override int GetHashCode()
        {
            return Id.GetHashCode();
        }
    }

    class StateMachine : IStateMachine
    {
        public IState CurrentState { get; protected set; }
        public List<IState> States { get; }

        public StateMachine()
        {
            States = new List<IState>();
        }

        public bool Transit(string transitionId, object args)
        {
            var newStateId = CurrentState.Transit(transitionId, args);
            if (newStateId == null)
                return false;
            var newState = States.FirstOrDefault(s => s.Id == newStateId);
            if (null == newState)
            {
                Global.LogError($"state: {newStateId} is not inited");
                return false;
            }

            CurrentState = newState;
            CurrentState.Enter(args);
            return true;
        }
    }

Test

    class TestStateMachine : StateMachine
    {
        public TestStateMachine()
        {
            var stateIdle = new State("idle");
            var transI2A = new Transition("I2A", "idle", "A");
            stateIdle.Transions.Add(transI2A);

            var stateA = new State("A");
            var transA2B = new Transition("A2B", "A", "B");
            var transA2C = new Transition("A2C", "A", "C");
            stateA.Transions.AddRange(new[] {transA2B, transA2C});

            var stateB = new State("B");
            var transB2C = new Transition("B2C", "B", "C");
            stateB.Transions.Add(transB2C);

            var stateC = new State("C");
            var transC2B = new Transition("C2B", "C", "B");
            var transC2E = new Transition("C2E", "C", "end");
            stateC.Transions.AddRange(new[] { transC2B, transC2E });

            var stateEnd = new State("end");

            States.AddRange(new[] {stateIdle, stateA, stateB, stateC, stateEnd});

            //initial start state
            CurrentState = stateIdle;
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            IStateMachine machine = new TestStateMachine();
            machine.Transit("I2A", null);
            machine.Transit("A2B", null);
            machine.Transit("B2C", null);
            machine.Transit("C2B", null);
            machine.Transit("B2C", null);
            machine.Transit("C2E", null);
            machine.Transit("E2A", null);

            Console.Read();
        }
    }

运行结果
状态机示例代码_第2张图片

你可能感兴趣的:(.net,statemachine)