敏捷软件开发 - 原则、模式与实践 —— 设计模式(十二)STATE模式

本文为敏捷软件开发 - 原则、模式与实践系列的一部分。

本文对应原书第29章

STATE模式

STATE模式既具有switch/case语句的效率又具有解释迁移表的灵活性。

敏捷软件开发 - 原则、模式与实践 —— 设计模式(十二)STATE模式
上图展示该模式的结构。Turnstile类拥有关于事件的公有方法以及关于动作的受保护方法。它持有一个指向TurnstileState接口的引用。当Turnstile的两个事件方法中的一个被调用时,它就把这个事件委托给Turnstilestate对象。Turnstilestate的方法实现了LOCKED状态下的相应动作。

TurnstileUnlockedState的方法实现了UNLOCKED状态下的相应动作。为了改变FSM的状态,就要把这两个派生类之一的实例赋值给Turnstile对象中的引用。

STATE模式和STRATEGY模式

STATE模式和STRATEGY模式类似,它们都有一个上下文类,都委托给一个具有几个派生类的多态基类。不同之处(见下图)在于,在STATE模式中,派生类持有回指向上下文的引用。派生类的主要功能是使用这个引用选择并调用上下文类中的方法。在STRATEGY模式中,不存在这样的限制以及意图。STRATEGY的派生类不必持有指向上下文类的引用,并且也不需要去调用上下文类的方法。所以,所有的STATE模式实例同样也是STRATEGY模式实例,但是并非所有的STRATEGY模式实例都是STATE模式实例。

敏捷软件开发 - 原则、模式与实践 —— 设计模式(十二)STATE模式

STATE模式的代价和收益

STATE模式彻底地分离了状态机的逻辑和动作。动作是在Context类中实现的,而逻辑则是分布在State类的派生类中。这就使得二者可以非常容易地独立变化、互不影响。例如,只要使用State类的另一个派生类,就可以非常容易地在一个不同的状态逻辑中重用Context类的动作。此外,我们也可以在不影响State派生类逻辑的情况下创建Context子类来更改或者替换动作实现。

该方法的另外一个好处就是它非常高效。它基本上和嵌套switch/case实现的效率完全一样。因此,该方法既具有表驱动方法的灵活性,又具有嵌套swtich/case方法的效率。

这项技术的代价体现在两个方面。第一,State派生类的编写完全是一项乏味的工作。编写一个具有20个状态的状态机会使人精神麻木。第二,逻辑分散。无法在一个地方就看到整个状态机逻辑。因此,这使得代码难以维护。这会使人想起嵌套switch/case方法的晦涩性。

完整内容请查看敏捷软件开发 - 原则、模式与实践系列