• 状态机学习及对一段 java 代码的改写


    《敏捷软件开发:原则、模式与实践》这本书中的第 29 章讲解了 State 模式,例子是地铁里的十字转门。书中对于状态机的实现,有一个范例是使用迁移表来实现(程序 29.12, P382),这里不列出详细代码。
    我在这个例子里面了解到,原来 java 还支持 private interface,并且可以不创建接口的实例,而直接生成一个实现了接口的对象。使用的语法是类似于 C# 里匿名函数一样的内嵌定义语法。

    不过,例子中的 interface 定义的作用,仅仅是为了能够方便的创建迁移表,以及在循环遍历迁移表的时候,可以用一致的语法去调用方法。这可不就是 C# 的 delegate 所起的作用吗?
    因此我用 C# 语法重写了这个例子,由于使用了 delegate,代码减少了大概一半。

    记得在网上也看到有不少说法称 C# 中 delegate 的设计违反了 OO 的设计原则,但是从这个例子中我们可以看到,delegate 确实非常方便,在某些情况下可以大幅度简化设计,相比而言原书上的 java 程序例子,在一个 class 内部定义 private interface,然后再定义其实现,导致了很多只有一句话的代理方法,感觉非常臃肿和复杂。最主要是这里的 interface 定义是 private 的,变得毫无疑义。因此用 delegate 语法替换是一种便捷而无害的做法。

    思考:并非纯粹 OO 的语言就是最好的语言,很多场景下,OO 跟过程式混合使用会带来更高的生产力。比如 python 和 delphi 就都支持这样的特性。

    附 C# 的实现代码:

    using System;
    using System.Collections.Generic;
    using System.Text;

    namespace StateMachine1
    {
        
    class Program
        {
            
    static void Main(string[] args)
            {
                TurnstileController controller 
    = new TurnstileController();
                Turnstile turn 
    = new Turnstile(controller);

                turn.DoEvent(Event.Coin);
                turn.DoEvent(Event.Coin);
                turn.DoEvent(Event.Pass);
                turn.DoEvent(Event.Pass);

                Console.ReadLine();
            }
        }

        
    public enum State
        {
            Locked,
            Unlocked
        }

        
    public enum Event
        {
            Coin,
            Pass
        }

        
    public class TurnstileController
        {
            
    public void Lock()
            {
                Console.WriteLine(
    "Lock");
            }

            
    public void Unlock()
            {
                Console.WriteLine(
    "Unlock");
            }

            
    public void Alarm()
            {
                Console.WriteLine(
    "Alarm");
            }

            
    public void ThankYou()
            {
                Console.WriteLine(
    "ThankYou");
            }
        }

        
    public class Turnstile
        {
            State state 
    = State.Locked;

            
    // 这个属性暴露出来是为了让测试类获取或设定十字转门的初始状态
            public State State
            {
                
    get { return state; }
                
    set { state = value; }
            }

            
    private TurnstileController controller;

            
    // 用 delegate 代替 java 的 private interface 实现
            private delegate void Action();

            
    // 表示状态迁移表的一个条目
            private class Transition
            {
                
    public State CurrentState;
                
    public Event Event;
                
    public State NewState;
                
    public Action Action;

                
    public Transition(State currentState, Event evt, State newState, Action action)
                {
                    
    this.CurrentState = currentState;
                    
    this.Event = evt;
                    
    this.NewState = newState;
                    
    this.Action = action;
                }
            }

            
    private List<Transition> transitions = new List<Transition>();

            
    public Turnstile(TurnstileController controller)
            {
                
    this.controller = controller;

                
    // 构造状态迁移表
                AddTransition(State.Locked, Event.Coin, State.Unlocked, new Action(controller.Unlock));
                AddTransition(State.Locked, Event.Pass, State.Locked, 
    new Action(controller.Alarm));
                AddTransition(State.Unlocked, Event.Coin, State.Unlocked, 
    new Action(controller.ThankYou));
                AddTransition(State.Unlocked, Event.Pass, State.Locked, 
    new Action(controller.Lock));
            }

            
    private void AddTransition(State currentState, Event evt, State newState, Action action)
            {
                transitions.Add(
    new Transition(currentState, evt, newState, action));
            }

            
    /// <summary>
            
    /// 处理事件
            
    /// </summary>
            
    /// <param name="evt"></param>
            public void DoEvent(Event evt)
            {
                
    foreach (Transition tran in transitions)
                {
                    
    if (state == tran.CurrentState && evt == tran.Event)
                    {
                        state 
    = tran.NewState;
                        tran.Action.Invoke();

                        
    // 原书遗漏这个操作
                        break;
                    }
                }
            }
        }
    }
  • 相关阅读:
    delphi SysErrorMessage 函数和系统错误信息表 good
    Delphi中ShellExecute使用详解(详细解释10种显示状态)
    几个获取Windows系统信息的Delphi程序
    判断操作系统多久没有任何操作
    MVC4+WebApi+Redis Session共享练习(下)
    MVC4+WebApi+Redis Session共享练习(上)
    EntityFramework使用总结(与MVC4.0实现CURD操作)
    MVC3.0+knockout.js+Ajax 实现简单的增删改查
    基于Redis缓存的Session共享(附源码)
    Redis缓存服务搭建及实现数据读写
  • 原文地址:https://www.cnblogs.com/RChen/p/489657.html
Copyright © 2020-2023  润新知