有人能说一个在软件中使用状态机的好例子(编译器和解析器除外)吗?有很多实际重要的例子,状态机的使用应该简化软件:-)
我想编写.NET应用程序。
感谢。
答案 0 :(得分:1)
您可以将每个UI视为一个大型状态机。用户界面中的每个事件(例如按钮点击,菜单选择等)都会推动转换到另一个状态,这可能意味着新页面。
答案 1 :(得分:1)
您的操作系统内核调度程序/调度程序是状态机。线程具有状态 - 运行,就绪,休眠,事件等待,暂停,终止。这些事件是IO设备驱动程序的硬件中断和运行线程的软件中断。
答案 2 :(得分:1)
显示典型导航路径的网站设计(类似于@ duffymo的回答)。这是一个不完整的例子(灵感来自“应用UML和模式”(Craig Larman)):
答案 3 :(得分:0)
另一种情况是订购。新订单(处于新状态)可以取消或修改,但不能退款。但是,一旦你处于完成状态,它就无法取消,但它可能会被退还。
答案 4 :(得分:0)
随机数生成器可以某种方式被视为状态机。你有一组输入,如左移,加常数,乘以常数等。状态是实际的当前随机值。由于这种随机数的计数是有限的,它可以被认为是某种有限状态机。
答案 5 :(得分:0)
对于状态机的一些示例(以Umple表示),请参阅:
运河锁软件: http://cruise.eecs.uottawa.ca/umpleonline/?example=CanalLockStateMachine&diagramtype=state
电信呼叫处理: http://cruise.eecs.uottawa.ca/umpleonline/?example=Phone&diagramtype=state
车库门软件: http://cruise.eecs.uottawa.ca/umpleonline/?example=GarageDoor&diagramtype=state
在机票预订系统中预订: http://cruise.eecs.uottawa.ca/umpleonline/?example=Booking&diagramtype=state
答案 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)
{
}
}