状态模式

当我们在对某个类的行为进行具体的操作时,往往要进行一些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的判断的逻辑,由传入不同对象来取代了,非常符合面向对象的设计思想,同时可以方便地扩展新的状态类,避免了丑陋的逻辑判断。

上一篇:coalesce和repartition的区别


下一篇:DNS解析中的A记录、AAAA记录、CNAME记录、MX记录、NS记录、TXT记录、SRV记录、URL转发等