当我们在对某个类的行为进行具体的操作时,往往要进行一些if else的判断,来确定对象中某些参数的状态,从而执行不同的行为。当判断的参数较多时,大量的if else就会变得很难维护,此时就需要用状态模式来处理了。
状态模式的核心思想是将对象的状态抽象出来,抽象的不同实现表示不同的状态。然后把对象的行为包装在不同的状态对象里,这样,我们传入不同的状态对象,原对象的具体行为就会发生改变。
例如,电梯的运行就可以分为不同的状态。我们创建如下接口来定义电梯的常见操作:
/** * 状态控制接口——电梯控制接口 */ public interface ElevatorController { //打开电源 void powerOn(); //关闭电源 void powerOff(); //开门 void openDoor(); //关门 void closeDoor(); //前往某个楼层 void goToFloor(int floor); }
其中,开门,关门,前往某个楼层这几个操作在电梯的不同状态会有不同的行为。如正在上下运行时无法开门或关门,电源关闭时这三个操作都不能执行等。
创建接口来定义要包装到状态对象中的行为:
/** * 状态模式——电梯状态接口 * 定义所有的操作,根据不同的状态,在实现类中对方法有不同的具体实现 */ public interface ElevatorState { void openDoor(); void closeDoor(); void goToFloor(int floor); }
创建状态的实现类,如电梯运行中,电梯暂停中,电梯停运:
/** * 状态实现类——电梯运行中 */ public class ElevatorInOperation implements ElevatorState { private ElevatorInOperation() { } public static ElevatorInOperation getInstance() { return InstanceHolder.instance; } @Override public void openDoor() { System.out.println("can not open the door in operation!"); } @Override public void closeDoor() { System.out.println("can not close the door in operation!"); } @Override public void goToFloor(int floor) { System.out.println("will go to " + floor + " floor"); } private static class InstanceHolder { private static ElevatorInOperation instance = new ElevatorInOperation(); } }
/** * 状态实现类——电梯暂停中 */ public class ElevatorInPause implements ElevatorState { private ElevatorInPause() { } public static ElevatorInPause getInstance() { return InstanceHolder.instance; } @Override public void openDoor() { System.out.println("open the door successful"); } @Override public void closeDoor() { System.out.println("close the door successful"); } @Override public void goToFloor(int floor) { System.out.println("will go to " + floor + " floor"); } private static class InstanceHolder { private static ElevatorInPause instance = new ElevatorInPause(); } }
/** * 状态实现类——电梯停运中 */ public class ElevatorInStop implements ElevatorState { private ElevatorInStop() { } public static ElevatorInStop getInstance() { return InstanceHolder.instance; } @Override public void openDoor() { System.out.println("can not open the door in stop!"); } @Override public void closeDoor() { System.out.println("can not close the door in stop!"); } @Override public void goToFloor(int floor) { System.out.println("can not add floor in stop!"); } private static class InstanceHolder { private static ElevatorInStop instance = new ElevatorInStop(); } }
这里我们只简单地打印了操作信息来代表行为的具体实现。最后再创建电梯控制接口的实现:
/** * 状态控制实现类——电梯控制实现类 */ public class ElevatorControllerImpl implements ElevatorController { private ElevatorState mState; public void setState(ElevatorState mState) { this.mState = mState; } @Override public void powerOn() { setState(ElevatorInPause.getInstance()); System.out.println("elevator is on"); } @Override public void powerOff() { setState(ElevatorInStop.getInstance()); System.out.println("elevator is off"); } @Override public void openDoor() { mState.openDoor(); } @Override public void closeDoor() { mState.closeDoor(); } @Override public void goToFloor(int floor) { if (!(mState instanceof ElevatorInStop)) { setState(ElevatorInOperation.getInstance()); System.out.println("will go to " + floor + " floor"); } mState.goToFloor(floor); } }
电梯控制实现类持有状态抽象的引用,行为方法中,状态类实现的操作就需要调用状态的行为方法,或传入其它的状态对象来改变电梯的状态。可以看到,本身需要多个if else的判断的逻辑,由传入不同对象来取代了,非常符合面向对象的设计思想,同时可以方便地扩展新的状态类,避免了丑陋的逻辑判断。