zoukankan      html  css  js  c++  java
  • C# 3.0下有限状态机的一种优雅的实现

    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));
                }
            }
        }

  • 相关阅读:
    vue实现左右两列竖直分别滑动,且双向关联的选项卡(一)
    根据对象的某个字段(值为数字)排序
    如何将data中字符传的换行正常显示
    HBase集群搭建部分配置
    YARN详解
    常用查询函数
    分桶表
    hive分区表
    xsync分发脚本
    ssh免密登录
  • 原文地址:https://www.cnblogs.com/TianFang/p/1017665.html
Copyright © 2011-2022 走看看