您的位置:首页 > 编程语言 > C#

C# 3.0下有限状态机的一种优雅的实现

2007-12-27 23:56 225 查看
C# 3.0下有限状态机的一种优雅的实现

实现状态机有多种模式,其中最灵活而强大的方式是通过迁移表来实现,该方式的缺点之一是需要编写大量小块代码去支持迁移表。而在C#3.0中,可以以一种非常优雅的方式实现。

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace StateMachine

{

class Program

{

static void Main(string[] args)

{

var door = new Door(State.Open);

while (true)

{

string s = Console.ReadLine();

Operation op = string.IsNullOrEmpty(s) ? Operation.Push : Operation.Pull;

door.Process(op);

}

}

}

enum Operation

{

Push, Pull

}

enum State

{

Open, Closed

}

class Door

{

public State State { get; set; }

Dictionary<State, Dictionary<Operation, Action>> rule;

public Door(State state)

{

this.State = state;

rule = new Dictionary<State, Dictionary<Operation, Action>>();

foreach (var e in Enum.GetValues(typeof(State)))

{

rule[(State)e] = new Dictionary<Operation, Action>();

}

InitOperationRule();

}

void InitOperationRule()

{

//正常操作

rule[State.Closed][Operation.Push] = () => { Console.WriteLine("门被推开了"); State = State.Open; };

rule[State.Open][Operation.Pull] = () => { Console.WriteLine("门被拉上了"); State = State.Closed; };

////加入几种特殊情况的处理

//rule[State.Closed][Operation.Pull] = () => Console.WriteLine("门是关上的,拉了也白拉");

//rule[State.Open][Operation.Push] = () => Console.WriteLine("门是开的,不用推了,直接进去吧");

}

public void Process(Operation op)

{

try

{

rule[State][op]();

}

catch (KeyNotFoundException)

{

Console.WriteLine(string.Format("门在{0}状态下不允许{1}操作", State, op));

}

}

}

}

从代码中可以看到,通过lambda表达式,可以简化迁移表的构造,并且更加直观。

通过迁移表构造状态机的一种不足在于查询速度,在本例中每个操作都要进行两次查询才能进行状态转换操作。如果状态较多则非常费时,这里我把它改进了一下,使得每次操作只需要查询一次即可。

class DoorPlus

{

State state;

public State State

{

get { return state; }

set

{

if (state != value)

currentOpRule = rule[value];

state = value;

}

}

Dictionary<Operation, Action> currentOpRule;

Dictionary<State, Dictionary<Operation, Action>> rule;

public DoorPlus(State state)

{

this.State = state;

rule = new Dictionary<State, Dictionary<Operation, Action>>();

foreach (var e in Enum.GetValues(typeof(State)))

{

rule[(State)e] = new Dictionary<Operation, Action>();

}

currentOpRule = rule[State];

InitOperationRule();

}

void InitOperationRule()

{

//正常操作

rule[State.Closed][Operation.Push] = () => { Console.WriteLine("门被推开了"); State = State.Open; };

rule[State.Open][Operation.Pull] = () => { Console.WriteLine("门被拉上了"); State = State.Closed; };

////加入几种特殊情况的处理

//rule[State.Closed][Operation.Pull] = () => Console.WriteLine("门是关上的,拉了也白拉");

//rule[State.Open][Operation.Push] = () => Console.WriteLine("门是开的,不用推了,直接进去吧");

}

public void Process(Operation op)

{

try

{

currentOpRule[op]();

}

catch (KeyNotFoundException)

{

Console.WriteLine(string.Format("门在{0}状态下不允许{1}操作", State, op));

}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: