实现状态机有多种模式,其中最灵活而强大的方式是通过迁移表来实现,该方式的缺点之一是需要编写大量小块代码去支持迁移表。而在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));
            }
        }
    }

Lambda表达式实现有限状态机的更多相关文章

  1. 你知道C#中的Lambda表达式的演化过程吗?

    那得从很久很久以前说起了,记得那个时候... 懵懂的记得从前有个叫委托的东西是那么的高深难懂. 委托的使用 例一: 什么是委托? 个人理解:用来传递方法的类型.(用来传递数字的类型有int.float ...

  2. Linq表达式、Lambda表达式你更喜欢哪个?

    什么是Linq表达式?什么是Lambda表达式? 如图: 由此可见Linq表达式和Lambda表达式并没有什么可比性. 那与Lambda表达式相关的整条语句称作什么呢?在微软并没有给出官方的命名,在& ...

  3. 背后的故事之 - 快乐的Lambda表达式(一)

    快乐的Lambda表达式(二) 自从Lambda随.NET Framework3.5出现在.NET开发者眼前以来,它已经给我们带来了太多的欣喜.它优雅,对开发者更友好,能提高开发效率,天啊!它还有可能 ...

  4. Kotlin的Lambda表达式以及它们怎样简化Android开发(KAD 07)

    作者:Antonio Leiva 时间:Jan 5, 2017 原文链接:https://antonioleiva.com/lambdas-kotlin/ 由于Lambda表达式允许更简单的方式建模式 ...

  5. java8中lambda表达式的应用,以及一些泛型相关

    语法部分就不写了,我们直接抛出一个实际问题,看看java8的这些新特性究竟能给我们带来哪些便利 顺带用到一些泛型编程,一切都是为了简化代码 场景: 一个数据类,用于记录职工信息 public clas ...

  6. 背后的故事之 - 快乐的Lambda表达式(二)

    快乐的Lambda表达式 上一篇 背后的故事之 - 快乐的Lambda表达式(一)我们由浅入深的分析了一下Lambda表达式.知道了它和委托以及普通方法的区别,并且通过测试对比他们之间的性能,然后我们 ...

  7. CRL快速开发框架系列教程二(基于Lambda表达式查询)

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  8. Lambda 表达式递归用法实例

    注意: 使用Lambda表达式会增加额外开销,但却有时候又蛮方便的. Windows下查找子孙窗口实例: HWND FindDescendantWindows(HWND hWndParent, LPC ...

  9. Spark中Lambda表达式的变量作用域

    通常,我们希望能够在lambda表达式的闭合方法或类中访问其他的变量,例如: package java8test; public class T1 { public static void main( ...

随机推荐

  1. 如何在Android开发中让你的代码更有效率

    最近看了Google IO 2012年的一个视频,名字叫做Doing More With Less: Being a Good Android Citizen,主要是讲如何用少少的几句代码来改善And ...

  2. Nmap / NetCat(nc) / 网络安全工具

    nmap - 网络探测工具和安全/端口扫描器 nmap [ <扫描类型> ...] [ <选项> ] { <扫描目标说明> } 描述 Nmap ("Net ...

  3. mysql explain中key_len的计算

    ken_len表示索引使用的字节数,根据这个值,就可以判断索引使用情况,特别是在组合索引的时候,判断是否所有的索引字段都被查询用到. key_len显示了条件检索子句需要的索引长度,但 ORDER B ...

  4. Delphi 让自己的软件实现双击打开文件 转

    unit shjAssociateFileType; interface uses Windows, Registry; {将文件类型strFileExtension与程序strExeFileName ...

  5. 细雨学习笔记:Jmeter参数化

    目前我用到两种方式: 1)某个参数,值不常改变的,好多地方都用到:请用“用户定义的变量” 用户组,右键--添加--配置原件--用户定义的变量,在这添加. 如何使用呢?在需要用到此参数的地方这样引用: ...

  6. ubuntu 下 数学库编译链接时找不到各种数学问题解决方法 can not fon atan 等等

    解决参考 http://askubuntu.com/questions/190246/ld-cannot-find-math-library you should use -lm at the end ...

  7. 提取数字、英文、中文、过滤重复字符等SQL函数(含判断字段是否有中文)

    --SQL 判断字段值是否有中文 create  function  fun_getCN(@str  nvarchar(4000))    returns  nvarchar(4000)      a ...

  8. Unity3d 基于物理渲染Physically-Based Rendering之specular BRDF

    在实时渲染中Physically-Based Rendering(PBR)中文为基于物理的渲染它能为渲染的物体带来更真实的效果,而且能量守恒 稍微解释一下字母的意思,为对后文的理解有帮助,从右到左L为 ...

  9. 如何给10^7个数据量的磁盘文件排序--bitset

    题目: 输入:给定一个文件,里面最多含有n个不重复的正整数(也就是说可能含有少于n个不重复正整数),且其中每个数都小于等于n,n=10^7.输出:得到按从小到大升序排列的包含所有输入的整数的列表. 分 ...

  10. BootStrap入门教程 (三) :可重用组件(按钮,导航,标签,徽章,排版,缩略图,提醒,进度条,杂项)

    上讲回顾:Bootstrap的基础CSS(Base CSS)提供了优雅,一致的多种基础Html页面要素,包括排版,表格,表单,按钮等,能够满足前端工程师的基本要素需求. Bootstrap作为完整的前 ...