管理状态的就是State模式。下面一边看Java的程序逻辑一边介绍。管理状态的一般程序如下所示。
public boolean handleEvent(Event evt) {
int& state;
switch (evt.id) {
case Event.COIN_INSERT:
if (vendmachine.CoinInsert(state))
state = COIN_INSERT;
break;
case Event.COIN_COMPLETE:
if (vendmachine.CoinComp(state))
state = COIN_ COMPLETE;
break;
}
}
这个例子中,在发动机箱这个程序中有加速和减速这两个性能。状态有等待状态和运转状态。
状态模型如图2所示。这是非常简单的例子。
将其状态Idle、Running分别作为EngineState的子类。在该子类中,将各自的状态发生的行为作为方法进行描述。那么如果用Java编码的话会变成什么样呢。
abstract class EngineState{
void Up(EngineBox eb){}
void Down(EngineBox eb){}
void Error(EngineBox eb){}
void ShowCurrentState(){}
}
class EngineRunning extends EngineState{
PrintPanel pt = new PrintPanel();
void Up(EngineBox eb){
pt.Print("No More Up");
eb.ChangeState(new EngineRunning());
}
void Down(EngineBox eb){
pt.Print("Down to idle from running");
eb.ChangeState(new EngineIdle());
}
void ShowCurrentState(){
pt.Print("State:running");
}
}
class EngineIdle extends EngineState{
PrintPanel pt = new PrintPanel();
void Up(EngineBox eb){
pt.Print("Up to running from idle");
eb.ChangeState(new EngineRunning());
}
void Down(EngineBox eb){
pt.Print("No More Down");
eb.ChangeState(new EngineIdle());
}
void ShowCurrentState(){
pt.Print("State:idle");
}
}
class EngineBox extends Object{
EngineState state;
EngineBox(){
state = new EngineIdle();
}
void Up(){
state.Up(this);
}
void Down(){
state.Down(this);
}
void ChangeState(EngineState newState){
state = newState;
state.ShowCurrentState();
}
}
关于编码的说明,EngineBox类的初期状态从图2的状态模型变成了Idle。这是通过state = new EngineIdle();进行的。
再看一下Up(),将EngineBox的对象-this (其自身)作为参数传送。因为这是从Up()中生成EngineBox的方法ChangeState()。
这时,为了改变状态new EngineRunning()从Idle变成Running状态。在EngineIdle、EngineRunning中,Up()、Down()对各自的行为进行编码。
因为OOP是解决难题的,大家也一边运行程序一边考虑逻辑。主要部分的生成简单地表示如下。
EngineBox ebox;
ebox = new EngineBox();
ebox.Up();
根据事件生成ebox.Down()和ebox.Up()。
改变式样,在运行中的状态中再试着增加一个low和high。因为State模式很灵活,只要稍微改变下子类就可以了。没有改变主要的EngineBox类。
类图如图4所示。
在不使用State模式的编码中加入新的状态的话,因为CASE语句中很多源代码都很零散,所以修改很花时间并且很容易出错。
相反,在State模式中创建要增加状态的子类后,只要改变该状态中行为的方法就可以了。不需要修改EngineBox类的编码。
<<修改后的Java编码>>
abstract class EngineState{
void Up(EngineBox eb){}
void Down(EngineBox eb){}
void ShowCurrentState(){}
}
class EngineRunningLow extends EngineState{
void Up(EngineBox eb){
System.out.println("Up to running high from low");
eb.ChangeState(new EngineRunningHigh());
}
void Down(EngineBox eb){
System.out.println("Down to idle from running low");
eb.ChangeState(new EngineIdle());
}
void ShowCurrentState(){
System.out.println("State:running low");
}
}
class EngineRunningHigh extends EngineState{
void Up(EngineBox eb){
System.out.println("No More Up");
eb.ChangeState(new EngineRunningHigh());
}
void Down(EngineBox eb){
System.out.println("Down to running low from high");
eb.ChangeState(new EngineRunningLow());
}
void ShowCurrentState(){
System.out.println("State:running high");
}
}
class EngineIdle extends EngineState{
void Up(EngineBox eb){
System.out.println("Up to running low from idle");
eb.ChangeState(new EngineRunningLow());
}
void Down(EngineBox eb){
System.out.println("No More Down");
eb.ChangeState(new EngineIdle());
}
void ShowCurrentState(){
System.out.println("State:idle");
}
}
class EngineBox extends Object{
EngineState state;
EngineBox(){
state = new EngineIdle();
}
void Up(){
state.Up(this);
}
void Down(){
state.Down(this);
}
void ChangeState(EngineState newState){
state = newState;
state.ShowCurrentState();
}
}
这样的话,State模式要根据状态用相同的方法名改变内容时,就能起作用。不足之处是状态增多时,只有那部分必须要生成子类。