Tom*_*nik 18 .net c# stateless-state-machine
我想在我的代码中使用http://code.google.com/p/stateless将功能与其依赖项分开.我没有找到任何高级的用法示例,所以这个问题是关于无状态框架的最佳实践.
我有以下配置(这只是一个例子,只有一个功能状态):
var stateMachine = new StateMachine(State.Stopped);
stateMachine.Configure(State.Stopped)
.Permit(Trigger.Failed, State.Error)
.Permit(Trigger.Succeed, State.GenerateMachineData);
stateMachine.Configure(State.GenerateMachineData)
.Permit(Trigger.Failed, State.Error)
.Permit(Trigger.Succeed, State.Finished);
public enum State
{
Stopped,
GenerateMachineData,
Finished,
Error
}
public enum Trigger
{
Succeed,
Failed
}
Run Code Online (Sandbox Code Playgroud)
那么在哪里调用实际的功能.我有以下想法,但每个都有优点和缺点:
1)在OnEntry()中设置功能以及下一次触发:
stateMachine.Configure(State.GenerateMachineData)
.OnEntry(() => {
try {
Generate();
stateMachine.Fire(Trigger.Succeed);
} catch {
stateMachine.Fire(Trigger.Error);
}
})
.Permit(Trigger.Failed, State.Error)
.Permit(Trigger.Succeed, State.Finished);
Run Code Online (Sandbox Code Playgroud)
那么如果我只是打电话
stateMachine.Fire(Trigger.Succeed);
Run Code Online (Sandbox Code Playgroud)
它最终在State.Finished或State.Error中结束
2)将状态机和功能分开,如:
__CODE__或__CODE__直接传入,因为这可能不是你想要发生的.即使他们这样做了,你仍然需要__CODE__/ __CODE__处理创建对象的错误.供应商是一种懒惰的回调,它允许一次性创建,使用和关闭实际对象,而不必进行大量的丑陋__CODE__/ __CODE__错误处理.
例如,只需查看将一个文件复制到另一个文件所需的代码(使用Guava实用程序将实际复制和流关闭代码最小化):
void DoTheStuff() {
switch (stateMachine.State)
{
State.Stopped:
stateMachine.Fire(State.Succeed);
break;
State.GenerateMachineData:
Generate();
stateMachine.Fire(State.Succeed);
break;
default:
throw new Exception();
}
}
void Main()
{
while (stateMachine.State != State.Succeed && stateMachine.State != State.Error)
{
DoTheStuff();
}
}
Run Code Online (Sandbox Code Playgroud)
如果您使用供应商,请查看代码:
var stateMachine = new StateMachine(State.Stopped);
stateMachine.Configure(State.Stopped)
.Permit(Trigger.Failed, State.Error)
.Permit(Trigger.Succeed, State.GenerateMachineData);
stateMachine.Configure(State.GenerateMachineData)
.Permit(Trigger.Failed, State.Error)
.Permit(Trigger.Succeed, State.Finished);
public enum State
{
Stopped,
GenerateMachineData,
Finished,
Error
}
public enum Trigger
{
Succeed,
Failed
}
Run Code Online (Sandbox Code Playgroud)
我喜欢他们在源代码中有的BugTrackerExample.
所以你的机器可能看起来像这样:
class Generator
{
private readonly StateMachine state;
public Generator()
{
state = new StateMachine(State.Stopped);
// your definition of states ...
state.Configure(State.GenerateMachineData)
.OnEntry(() => { Generate(); })
.Permit(Trigger.Failed, State.Error)
.Permit(Trigger.Succeed, State.Finished);
// ...
}
public void Succeed()
{
state.Fire(Trigger.Succeed);
}
public void Fail()
{
state.Fire(Trigger.Fail);
}
public void Generate()
{
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,测试不应该是问题.
如果需要进一步分离,可以使用事件,委托或策略模式而不是Generate方法.