👉文章示例代码👈

定义

当一个对象的内在状态改变时允许改变其行为。

状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂的情况。可以将状态的判断逻辑转移到表示不同状态的一系列类当中,从而简化复杂的判断逻辑。

三个角色

状态模式主要有以下三个角色:

  • 环境类Context:也叫做上下文,维护一个当前状态,并将与状态相关的操作委托给当前状态对象来处理。
  • 抽象状态类State:定义一个接口用来封装环境对象中特定状态相关的行为。
  • 具体状态类Concrete State:实现抽象状态类对应的行为。

场景示例

笔者这里以开关灯为例,主要有开、关两种状态。

创建抽象状态类

/**
 * @author zhh
 * @description 电灯状态类(抽象状态类)
 * @date 2020-03-03 22:38
 */
public abstract class ElectricLightState {

    protected ElectricLightContext electricLightContext;

    public void setElectricLightContext(ElectricLightContext electricLightContext) {
        this.electricLightContext = electricLightContext;
    }

    /**
     * 开灯
     */
    public abstract void turnOn();

    /**
     * 关灯
     */
    public abstract void turnOff();

    /**
     * 获取状态
     */
    public abstract String getState();
}

创建具体状态类

/**
 * @author zhh
 * @description 打开状态
 * @date 2020-03-03 22:42
 */
public class TurnOnState extends ElectricLightState {

    @Override
    public void turnOn() {
        System.out.println("操作错误, 当前电灯状态已经是打开状态");
    }

    @Override
    public void turnOff() {
        super.electricLightContext.setElectricLightState(ElectricLightContext.TURN_OFF_STATE);
    }

    @Override
    public String getState() {
        return "打开状态";
    }
}


/**
 * @author zhh
 * @description 关闭状态
 * @date 2020-03-03 22:43
 */
public class TurnOffState extends ElectricLightState {

    @Override
    public void turnOn() {
        super.electricLightContext.setElectricLightState(ElectricLightContext.TURN_ON_STATE);
    }

    @Override
    public void turnOff() {
        System.out.println("操作错误, 当前电灯状态已经是关闭状态");
    }

    @Override
    public String getState() {
        return "关闭状态";
    }
}

创建环境类

/**
 * @author zhh
 * @description 电灯环境类(环境类)
 * @date 2020-03-03 22:39
 */
public class ElectricLightContext {

    private ElectricLightState electricLightState;

    public final static TurnOnState TURN_ON_STATE = new TurnOnState();

    public final static TurnOffState TURN_OFF_STATE = new TurnOffState();

    public ElectricLightState getElectricLightState() {
        return electricLightState;
    }

    public void setElectricLightState(ElectricLightState electricLightState) {
        this.electricLightState = electricLightState;
        // 将当前的环境通知到各个状态实现类
        this.electricLightState.setElectricLightContext(this);
    }

    public void turnOn() {
        this.electricLightState.turnOn();
    }

    public void turnOff() {
        this.electricLightState.turnOff();
    }
}

这里维护一个当前状态对象,并将 turnOff() 、 turnOn() 这些与状态相关的操作委托给当前的状态对象来进行处理。

测试类及输出

/**
 * @author zhh
 * @description 测试类
 * @date 2020-03-03 22:55
 */
public class Test {

    public static void main(String[] args) {
        ElectricLightContext electricLightContext = new ElectricLightContext();
        electricLightContext.setElectricLightState(new TurnOnState());
        System.out.println(String.format("当前电灯的状态: [%s]", electricLightContext.getElectricLightState().getState()));
        electricLightContext.turnOn();

        electricLightContext.turnOff();
        System.out.println(String.format("当前电灯的状态: [%s]", electricLightContext.getElectricLightState().getState()));
    }
}

测试类的输出结果如下:

当前电灯的状态: [打开状态]

操作错误, 当前电灯状态已经是打开状态

当前电灯的状态: [关闭状态]

类结构图

以上示例类的结构图如下所示

image.png

总结

适用场景

  • 当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时。
  • 业务场景中有多个状态,且这些状态的变化都需要依靠大量的多分支判断语句来实现。

优点

  • 将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。
  • 易扩展。通过定义新的子类可以很容易增加新的状态和转换。
  • 通过把各种状态转移逻辑分布到State的子类之间,来减少相互间的依赖。

缺点

在状态多的业务场景当中使用,会导致类数目的增加,使系统变得复杂。

参考