Lambda表达式实现有限状态机
实现状态机有多种模式,其中最灵活而强大的方式是通过迁移表来实现,该方式的缺点之一是需要编写大量小块代码去支持迁移表。而在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表达式实现有限状态机的更多相关文章
- 你知道C#中的Lambda表达式的演化过程吗?
那得从很久很久以前说起了,记得那个时候... 懵懂的记得从前有个叫委托的东西是那么的高深难懂. 委托的使用 例一: 什么是委托? 个人理解:用来传递方法的类型.(用来传递数字的类型有int.float ...
- Linq表达式、Lambda表达式你更喜欢哪个?
什么是Linq表达式?什么是Lambda表达式? 如图: 由此可见Linq表达式和Lambda表达式并没有什么可比性. 那与Lambda表达式相关的整条语句称作什么呢?在微软并没有给出官方的命名,在& ...
- 背后的故事之 - 快乐的Lambda表达式(一)
快乐的Lambda表达式(二) 自从Lambda随.NET Framework3.5出现在.NET开发者眼前以来,它已经给我们带来了太多的欣喜.它优雅,对开发者更友好,能提高开发效率,天啊!它还有可能 ...
- Kotlin的Lambda表达式以及它们怎样简化Android开发(KAD 07)
作者:Antonio Leiva 时间:Jan 5, 2017 原文链接:https://antonioleiva.com/lambdas-kotlin/ 由于Lambda表达式允许更简单的方式建模式 ...
- java8中lambda表达式的应用,以及一些泛型相关
语法部分就不写了,我们直接抛出一个实际问题,看看java8的这些新特性究竟能给我们带来哪些便利 顺带用到一些泛型编程,一切都是为了简化代码 场景: 一个数据类,用于记录职工信息 public clas ...
- 背后的故事之 - 快乐的Lambda表达式(二)
快乐的Lambda表达式 上一篇 背后的故事之 - 快乐的Lambda表达式(一)我们由浅入深的分析了一下Lambda表达式.知道了它和委托以及普通方法的区别,并且通过测试对比他们之间的性能,然后我们 ...
- CRL快速开发框架系列教程二(基于Lambda表达式查询)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- Lambda 表达式递归用法实例
注意: 使用Lambda表达式会增加额外开销,但却有时候又蛮方便的. Windows下查找子孙窗口实例: HWND FindDescendantWindows(HWND hWndParent, LPC ...
- Spark中Lambda表达式的变量作用域
通常,我们希望能够在lambda表达式的闭合方法或类中访问其他的变量,例如: package java8test; public class T1 { public static void main( ...
随机推荐
- Oracle RAC 客户端连接负载均衡(Load Balance)
实现负载均衡(Load Balance)是Oracle RAC最重要的特性之一,主要是把负载平均分配到集群中的各个节点,以提高系统的整体吞吐能力.通常情况下有两种方式来实现负载均衡,一个是基于客户端连 ...
- Win7下硬盘安装Centos5.3
前提声明:一个硬盘最多只能有四个主分区,也就是hda1,hda2,hda3和hda4,逻辑分区都是从hda5开始 一.软件准备:EasyBCD+分区助手+Centos 5.3 ISO镜像文件: 二.W ...
- Bug疑难杂症 - java.lang.NoSuchFieldError: udhLen
通过友盟后台记录到一个诡异的错误: HUAWEI C8825D 4.0.4 百度.谷歌都未能找到一丝结果更别提解决方案. java.lang.NoSuchFieldError: udhLen at a ...
- VMtools安装以及设置
一.安装VMtools 点击VMware菜单的——虚拟机——安装VMware Tools,在弹出的对话框中选择“安装”.这时,在Ubuntu下会自动加载Linux版的VMware Tools的安装光盘 ...
- VS中使用QT调用R脚本
一开始想直接把R编译成库然后调用R,后来查了n多资料,发现VS中是无法办到的,官方也给出了一句话,大概意思就是没可能在VS中使用R提供的C++接口,大概是涉及到了底层的ABI的原因,具体也不太清楚. ...
- PHP获取Cookie模拟登录
关键字:CURL Cookie CURLOPT_COOKIEJAR CURLOPT_COOKIEFILE 模拟登录 PHP作者:方倍工作室原文:http://www.cnblogs.com/txw19 ...
- 读《HTML5与CSS3权威指南(上册)》笔记
第二章 1.内容类型:“text/html”.DOCTYPE声明:<!DOCTYPE html>.指定字符编码:<meta charset="utf-8"> ...
- 20150913K-means聚类
1.聚类的思想: 将一个有N个对象的数据集,构造成k(k<=n)个划分,每个划分代表一个簇.使得每个簇包含一个对象,每个对象有且仅属于一个簇.对于给定的k,算法首先给出一个初始的划分方法,以后通 ...
- 实现 Web 后端和客户端之间的分布式和认证通讯
stack.io 是一个用于实现 Web 后端和客户端之间的分布式和认证通讯. 服务器端进程之间的通讯是非常高效的,因为没有中间的代理.而来自客户端的请求通过 socket.io 进入 Node.js ...
- Centos6.4 coll linux 10.2
由于oracle10g太老了,只怪他娘Oracle生它生的太早了,差点就没赶上新时代(这家伙内心可也有些挺自豪的东东的,人家很有可能跟着它的主要干爹工程师为雅典奥运贡献了门票哩,生逢盛会啊!),较Ce ...