2010-04-26 70 views
3

我想模拟一种有限状态机(有限状态机)。我有一系列状态(比如,从StateA到StateZ)。这个序列被称为一个链,并在内部实现为一个List。我将按照我希望它们运行的​​顺序添加状态。设计状态链

我的目的是能够在我的电脑中制作一系列动作(例如,鼠标点击)。 (我知道这已经完成了数十亿次)。

所以的状态定义为:

  1. boolean Precondition() < - 检查是否为这种情况下,有些情况是真实的。例如,如果我想单击程序的“记录”按钮,在此方法中,我将检查程序的进程是否正在运行。如果是,则转到链表中的下一个状态,否则,转到定义为失败状态的内容(通常是它们的第一个状态)。
  2. IState GetNextState() < - 返回下一个要评估的状态。如果Precondition()成功,它应该产生链中的下一个状态,否则它应该产生失败状态。
  3. Run()只需检查Precondition()并设置内部数据,以使GetNextState()按预期工作。

于是,一个很自然的做法,这将是这样的:

Chain chain = new Chain(); 
//chain.AddState(new State(Precondition, FailState, NextState) <- Method structure 
chain.AddState(new State(new WinampIsOpenCondition(), null, new <problem here, I want to referr to a state that still wasn't defined!>); 

最大的问题是,我想打,在这一点仍然没有被定义为一个国家的参考。我可以通过使用字符串来回避状态并使用内部散列表来避开这个问题,但是没有更清晰的选择吗?

我只能在构造函数中传递前提条件和失败状态,让执行前的链条在每个状态下将正确的下一个状态放在公共属性中,但这看起来有些尴尬。

回答

2

你可以做以下之一:

  • 定义nextState为您的站t E级内的可变场,及导线上之后使用突变的状态;例如setNextStatesetNextState方法可以被实现为只允许它被调用一次;随后的调用将导致IllegalStateException被抛出。
  • 更改State接口以简单返回是否满足前提条件(即,返回boolean),并在满足前提条件时使用外部“协调器”类沿列表进行转换。换句话说,你知道,未来状态是在索引i + 1所以有没有真正的需要每个国家都有它的后继的显性知识。

鉴于你的状态机的简单起见,我赞成第二种方法。

1

这可以为Decorator模式一个完美的候选人。下一步装饰(包装)当前步骤。你可以建立整个国家链。

1

我同意@Adamski的第二点。除非您打算将状态作为图算法进行遍历,而不是使用外部中介来管理遍历,否则状态不需要知道自己的位置。

如果你真的有兴趣的国家居然能可表示为一棵树(即使它完全线性的目前)回答您的new <problem here, I want to referr to a state that still wasn't defined!>);

的方式问题,我会解决这个问题是每一个行动我记录我会设置任何类型的容器,如数组来保存一系列操作。然后我会记录当前的操作,但是延迟将它添加到容器中。当我记录第二个动作时,我会将它添加到前一个动作中,并将前一个动作放到数组上,然后保持当前动作。

当您进入执行调用时,您将推动不在容器上的最终操作以及定义FSM结束的操作。

所以,你会是这样的

public State PreviousAction { get; set; } 
public IList<State> States { get; private set } 
public void QueueAction(State CurrentAction) 
{  
    if(PreviousAction != null) 
    {   
     States.Add(new State(PreviousAction, CurrentAction)   
    } 

    PreviousAction = CurrentAction;  
} 

public void Execute() 
{  
    States.Add(new State(PreviousAction, State.Terminator)); 

    States[0].Execute();  
}