状态模式使用方法

3

我正在尝试基于修改版的状态模式,使用方法作为状态而不是类来实现简单的状态机,就像这样:

private Action<Input> currentState;
private void NextState(Input i) {
    currentState(i);
}

private void State1(Input i) {
    if( i ... )
        currentState = State1;
    else
        currentState = State2;
}

private void State2(Input i) {
    if( i ... )
        currentState = State1;
    else
        currentState = State2;  
}

但如果我能这样做会更加优雅:

private void NextState(Input i) {
    currentState = currentState(i);
}

private Func<xxx> State1() {
    if( i ... )
        return State1;
    else
        return State2;
}

但我不知道如何编写这个Func函数。有没有什么方法可以做到这一点呢?


也许我不熟悉你正在做的事情,但通常状态机由单个状态变量定义。这通常最好通过状态的“枚举”来描述。 - Jonathon Reinhart
3个回答

4
如果您想要使用返回void的函数,尝试使用Action代替。
private Action State1() {
    if( ... )
        return State1Inner;
    else
        return State2Inner;
}

如果您想使用返回具有自己签名的函数的函数,则必须首先定义一个自定义委托类型。以下是通用版本:
public delegate State<T> State<T>(T input);

private State<int> State1(int input) {
    if( ... )
        return State1;
    else
        return State2;
}

这将有助于避免使用内部状态函数。

2
+1. 对于传统的FSM,应该使用“Action<TInput>”,因为状态转换应该基于某种输入值发生。 - Alexei Levenkov
我希望它简单明了,没有内部状态,也就是说,一个状态应该能够返回自身或其他状态(基于某些TInput,这在我的示例中没有写出来)。因此,状态不会返回void,问题是我不知道它返回什么。 - Roberto
@Roberto 那么您需要定义一个自定义委托。请参考我的更新答案。 - p.s.w.g
@p.s.w.g 谢谢。我对编写一个类型为方法本身的委托感到困惑。我仍然不明白为什么它不能是 public delegate State<int> State<int>(int input); - Roberto
@Roberto,它可以只是public delegate State State(int input),但那样它就不会是通用的了。 - p.s.w.g

1

0

如果你想将方法用作状态并以某种方式“通用”地引用它们,那么你需要使用函数指针。我不熟悉c#中的语法,但在c++中,你可以传递一个指向函数的指针,并使用其指针调用该函数。实质上,这意味着将函数用作参数/变量-一种在运行时之前未知的操作。

了解一下函数指针,我认为这将让你达到你需要的目的,尽管我对你在这里具体做什么的性质很好奇。

如果你正在使用c#,它使用称为函数委托的东西而不是指针。阅读这里:http://msdn.microsoft.com/en-us/library/ms173171.aspx


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接