State Machine的例子

时间:2012-04-20 20:04:22

标签: design-patterns state state-machine

有人能说一个在软件中使用状态机的好例子(编译器和解析器除外)吗?有很多实际重要的例子,状态机的使用应该简化软件:-)

我想编写.NET应用程序。

感谢。

9 个答案:

答案 0 :(得分:1)

您可以将每个UI视为一个大型状态机。用户界面中的每个事件(例如按钮点击,菜单选择等)都会推动转换到另一个状态,这可能意味着新页面。

答案 1 :(得分:1)

您的操作系统内核调度程序/调度程序是状态机。线程具有状态 - 运行,就绪,休眠,事件等待,暂停,终止。这些事件是IO设备驱动程序的硬件中断和运行线程的软件中断。

答案 2 :(得分:1)

显示典型导航路径的网站设计(类似于@ duffymo的回答)。这是一个不完整的例子(灵感来自“应用UML和模式”(Craig Larman)):

enter image description here

答案 3 :(得分:0)

另一种情况是订购。新订单(处于新状态)可以取消或修改,但不能退款。但是,一旦你处于完成状态,它就无法取消,但它可能会被退还。

答案 4 :(得分:0)

随机数生成器可以某种方式被视为状态机。你有一组输入,如左移,加常数,乘以常数等。状态是实际的当前随机值。由于这种随机数的计数是有限的,它可以被认为是某种有限状态机。

答案 5 :(得分:0)

答案 6 :(得分:0)

opengl库是一个状态机。它保持一个状态,该状态根据对库函数的调用而变化。你可以在这里看到它:http://www.cs.tufts.edu/research/graphics/resources/OpenGL/OpenGL.htm

可以使用状态机的另一个范围是视频游戏。想象一下相对聪明的敌人。这个敌人会有几种状态:攻击,隐藏,死亡,跑步等。这可以通过状态和事件来控制。当我写一个视频游戏作为我的学位项目时,我使用了两个状态机:一个用于游戏流程(演示屏幕,游戏,选项等),另一个用于游戏本身(提问,投掷骰子,移动玩家等等) )

答案 7 :(得分:0)

这是一个基本FSM的玩具控制台应用程序示例。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

//  DESC: QAD-FSM (Quick And Dirty Finite State Machine)
//  
//  Notes: In its simplest form a state machine is
//       • A set of states
//       • A set of events
//       • A set of transitions that define 
//           the next state given the current state and event.
//       • A method of tracking current state
// 
//  Example:
// 
//       I want to create a different kind of door lock that
//           has the following states:
//          
//               1. LBS - Locked_Both_Sides
//               2. UBS - Unlocked_Both_Sides
//               3. LFO - Locked_From_Outside
// 
//           and has the following events:
//          
//               1. OKT - Outside Key Turn
//               2. IKT - Inside Key Turn
//              
//       Transistions will be as follows:
//      
//       CurrState  Event   NextState   Desc
//       ========================================================
//       LBS            OKT     UBS         When both sides locked, outside key turn unlocks both sides
//       LBS            IKT     LFO         When both sides locked, inside key turn unlocks inside
//       UBS            OKT     LFO         When both sides unlocked, outside key turn locks outside
//       UBS            IKT     LBS         When both sides unlocked, inside key turn locks both sides
//       LFO            OKT     UBS         When only outside locked, outside key turn unlocks outside
//       LFO            IKT     LBS         When only outside locked, inside key turn locks both sides.

namespace FSM
{
    // The FSM states
    enum State
    {
        LBS,
        UBS,
        LFO
    }

    // The FSM events
    enum Event
    {
        IKT,
        OKT
    }

    class Transition
    {
        public State currState { get; set; }
        public Event evnt { get; set; }
        public State nextState { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var fsm = new FSM();

            System.Console.WriteLine("Current State: " + fsm.StateDesc[fsm.CurrentState]);

            string input = "";
            while (input != "x")
            {
                System.Console.Write("Enter key turn [IKT, OKT] or x to exit: ");
                input = System.Console.ReadLine();
                if (input == "x") break;
                Event evnt;
                if (!Enum.TryParse(input, out evnt))
                {
                    System.Console.WriteLine("Invalid input: " + input + ", enter one of [IKT,OKT,x]");
                    continue;
                }
                fsm.ChangeState(evnt);
                System.Console.WriteLine("New State: " + fsm.StateDesc[fsm.CurrentState]);
            }

            System.Console.WriteLine("");
            System.Console.WriteLine("History");
            System.Console.WriteLine("===============================================");
            System.Console.WriteLine("CurrState(Event) => NextState");
            System.Console.WriteLine("===============================================");
            fsm.hist
                .Select(h => h.currState.ToString() + "(" + h.evnt.ToString() + ") => " + h.nextState.ToString())
                .ToList()
                .ForEach(h => System.Console.WriteLine(h));
        }
    }

    class FSM
    {
        public Dictionary<State, String> StateDesc = new Dictionary<State, String>()
                                                { 
                                                    {State.LBS, "Both Sides Locked"},
                                                    {State.LFO, "Locked From Outside"},
                                                    {State.UBS, "Both Sides Unlocked"}
                                                };

        public List<Transition> hist = new List<Transition>();

        // Create FSM transitions.
        List<Transition> trans = new List<Transition>
            {
                new Transition() { currState = State.LBS, evnt = Event.OKT, nextState = State.UBS }, 
                new Transition() { currState = State.LBS, evnt = Event.IKT, nextState = State.LFO }, 
                new Transition() { currState = State.UBS, evnt = Event.OKT, nextState = State.LFO }, 
                new Transition() { currState = State.UBS, evnt = Event.IKT, nextState = State.LBS }, 
                new Transition() { currState = State.LFO, evnt = Event.OKT, nextState = State.UBS }, 
                new Transition() { currState = State.LFO, evnt = Event.IKT, nextState = State.LBS }, 
            };

        public State CurrentState { get { var lt = hist.FirstOrDefault(); return lt == null ? State.UBS : lt.nextState; } }

        public State? ChangeState(Event evnt)
        {
            var t = trans.Find(r => r.currState == CurrentState && r.evnt == evnt);
            if (t == null) return null; // If you don't create transitions that cover all combinations this could happen.
            hist.Insert(0, t);
            return t.nextState;
        }
    }
}

答案 8 :(得分:0)

您可以使用面向方面的编程作为实现示例来查看.net中的通用状态机。

它可以在需要某些工作流程逻辑(例如批准工作流程)的软件中使用。

https://github.com/rcarubbi/carubbi.statemachine

只需这样创建您的实体:

    [InitialState("State1")]
    public class Entity : IStatedEntity
    {

        [Transition(From = "State1", To = "State2")]
        [Transition(From = "State3", To = "State1")]
        public void Method1()
        {
            Trace.WriteLine("Method1");
        }

        [Transition(From = "State2", To = "State1")]
        public string Method2()
        {
            Trace.WriteLine("Method2");
            return string.Empty;
        }

        [Transition(From = "State2", To = "State3")]
        [Transition(From = "State3", To = "State4")]
        public int Method3(int p1, int p2)
        {
            Trace.WriteLine("Method3");
            return p1 + p2;
        }


        public StateMachine StateMachine { get; set; }
   }

并以这种方式使用它:

      [TestMethod]
        public void TestMethod1()
        {
            StateMachine.Configure();
            var ent = new Entity
            {
                StateMachine =
                {
                    IgnoreInvalidOperations = true
                }
            };

            ent.StateMachine.TransitionStarted += StateMachine_TransitionStarted;
            ent.StateMachine.TransitionEnded += StateMachine_TransitionEnded;

            Trace.WriteLine(ent.StateMachine.CurrentState);
            ent.Method1();
            Trace.WriteLine(ent.StateMachine.CurrentState);
            ent.Method2();
            Trace.WriteLine(ent.StateMachine.CurrentState);
            ent.Method1();
            Trace.WriteLine(ent.StateMachine.CurrentState);
            var result = ent.Method3(2, 4);
            Trace.WriteLine(ent.StateMachine.CurrentState);
            var result2 = ent.Method3(4, 4);
            Trace.WriteLine(ent.StateMachine.CurrentState);
            var result3 = ent.Method3(4, 4);
            Trace.WriteLine(ent.StateMachine.CurrentState);
        }

        private void StateMachine_TransitionEnded(object sender, TransitionEventArgs e)
        {

        }


        private void StateMachine_TransitionStarted(object sender, TransitionStartedEventArgs e)
        {

        }
   }