曾经跟同事探讨过怎样给电梯的控制系统编程,讨论结果是如果用结构化的方式编写电梯的控制程序,系统一定很复杂很庞大。后来我用状态模式编写了一个简单的电梯控制程序,结果问题得到了极大的简化。以下是我编写的一个简单的单部电梯的控制程序的架构:
状态模式稍微复杂一些,首先,我们分析一部电梯可执行的动作有:关门、开门、上行、下行、停止。因此我们定义了一个ElevatorState接口,接口中有closeDoor()、openDoor()等五种电梯可执行的动作。
然后我们分析,单部电梯应有多种状态,包括:门关闭、门打开、上行中、下行中、已停止。因此我们定义了五个实现ElevatorState接口的类,DoorCloseState、DoorOpenState、MovingUpState、MovingDownState、StopState,分别对应电梯五种状态。五个状态类中都包括一个Elevator类型的成员,即电梯的类。
电梯类Elevator中有代表五种状态的成员,都是ElevatorState接口类型。Elevator类的构造方法中为代表五种状态的成员创建对应的实现类并赋值,如下:
publicElevator() {
stopState= new StopState(this);
movingUpState= new MovingUpState(this);
movingDownState= new MovingDownState(this);
doorOpenState= new DoorOpenState(this);
doorCloseState= new DoorCloseState(this);
state= stopState;
}
Elevator类中还有个call方法,代表用户呼叫电梯的动作,调用电梯当前状态的关门、上行或下行、停止、开门等动作,如下:
publicvoid call(int destFloor) {
if(destFloor != currentFloor) {
state.closeDoor();
if(destFloor > currentFloor) {
state.moveUp(destFloor);
}else if (destFloor < currentFloor) {
state.moveDown(destFloor);
}
state.stop();
state.openDoor();
}else {
System.out.println("Elevatoris at " + destFloor + " floor now.");
}
}
可以看出,对电梯能否执行当前动作,如何执行的逻辑被封装在电梯的状态类中,如此对逻辑的判断相对要简单的多,不用考虑多种状态下的情况,只考虑当前状态下如何处理,例如我们看一下电梯上行状态时如何处理开门动作:
publicvoidopenDoor()
{
System.out.println("Can‘topen
the door during move.");
}
可见此时不需要做任何逻辑判断,直接告诉用户:“在电梯移动中不能开门”。
状态模式针对对象可执行的动作与状态相关,而状态有很多的情况,此时使用状态模式将大大简化对逻辑的判断,使得代码条理清晰,不易混淆和出错。