状态机学习及对一段 java 代码的改写
2006-08-29 17:19
435 查看
《敏捷软件开发:原则、模式与实践》这本书中的第 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;
}
}
}
}
}
我在这个例子里面了解到,原来 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;
}
}
}
}
}
相关文章推荐
- 状态机学习及对一段 java 代码的改写
- java学习-【转】如何用Java编写一段代码引发内存泄露
- java并发编程学习之一段简单代码证明synchronized锁的是对象
- Java入门学习-学会用txt文档写一段helloworld,并通过windows命令行编译和执行该Java代码
- C#与Java对比学习:类型判断、类与接口继承、代码规范与编码习惯、常量定义
- [原]Java多线程编程学习笔记之八:死锁(含代码)
- 数据结构(Java 插入排序模拟)本代码重在学习数据结构思路,代码完整性欠缺,请见谅
- java如何从一段html代码中获取图片的src路径
- java设置一段代码执行的超时时间的简单方法 间接实现获取Connection超时问题
- 一个java状态机样例的代码
- (转载)JVM学习笔记(二)------Java代码编译和执行的整个过程
- java开源代码学习
- JAVA语言代码学习笔记
- java例题学习:简单的继承代码小片段
- JAVA学习代码——短信验证码倒计时功能
- 学习如何在 Java 代码中启用和禁用断言
- 一段有用的java3d代码,演示了java3d鼠标滑过对象事件。
- 学习Java过程中关于金字塔和镂空金字塔形状图形绘制的代码
- openSSL学习例子(代码含c与java两版本)
- 【Java学习笔记之十三】初探Java面向对象的过程及代码实现