假设我们有一个(英国)交通灯模拟应用程序,并且一个类TrafficLight有一个相关的有限状态机,定义为:-
* --> RED --> RED_AMBER --> GREEN --> AMBER --> RED --> ...
(repeat until the proverbial cows make an appearance )
在构建时 TrafficLight的状态是 RED 某种时间触发器会导致状态变化。
在应用程序中可能有一些代码,例如(删除任何带走点的代码)......
TrafficLight trafficLightsAtBigJunction = new TrafficLight(); // state = RED
trafficLightsAtBigJunction.setState( TrafficLightState.RED_AMBER );
trafficLightsAtBigJunction.setState( TrafficLightState.GREEN );
trafficLightsAtBigJunction.setState( TrafficLightState.AMBER );
trafficLightsAtBigJunction.setState( TrafficLightState.RED );
trafficLightsAtBigJunction.setState( TrafficLightState.RED_AMBER );
:
:
:
关键是,使用状态模式来实现状态机,如果我们这样做
TrafficLight trafficLightsAtBigJunction = new TrafficLight(); // state = RED
trafficLightsAtBigJunction.setState( TrafficLightState.GREEN ); // Exception!!!!!
抛出异常(根据我们的设计),因为它是非法的状态移动。这就是我们想要的。世界上的一切都很好。
但是,如果我们继续保持红绿灯并且它恰好处于状态 = AMBER 说那么似乎有问题。当我们的用户在 3 天后回来观看令人敬畏的交通灯模拟时,它会从某些(谁在乎)持久存储中的当前状态恢复。
我们如何在不破坏此处状态模式提供的封装的情况下使交通灯实例处于状态 AMBER?
似乎有 2 个选择:- (1) 创建一个新实例并运行相关状态 (2) 提供一种特殊方法来将状态设置为我们想要的任何状态,按照惯例,只有在从一些持久性存储中读取后才会使用. 例如
trafficLight.setStateAfterReadingFromPersistanceSource( AMBER );
我看到的(1)的问题是,在运行状态时很可能会出现我不想要的副作用,而且逻辑可能非常复杂,具体取决于状态机
(2) 的问题显然是它只能按约定工作,因此可能会在不知道何时不正确使用的情况下引入错误。更重要的是,它几乎打破了所有你想要的漂亮模式封装。
问题与持久性技术无关 - ORM、文件、序列化等问题相同
我假设这里有一个解决方案,但我自己想不出一个解决方案,而且我的谷歌搜索技能还不够。
任何指针都会很棒。