【设计模式】一文快速搞懂状态模式

2024-07-08 10:25:56 浏览数 (2)

引入

试着思考下这个功能如何实现:电灯有两种状态:开启(On)和 关闭(Off)。

当电灯处于不同的状态下,按下开关会触发不同的行为:

  • 电灯处于On状态时,按下开关,电灯会处于Off状态;
  • 电灯处于Off状态时,按下开关 ,电灯会处于On状态。

方案一:if-else实现

具体逻辑实现代码

代码语言:Java复制
class Light {

    // 电灯状态
    private boolean isOn;

    public Light() {
     // 初始状态为关闭
        this.isOn = false; 
    }

   // 不同状态按下开关逻辑
    public void toggleSwitch() {
        if (isOn) {
        // 开启状态按下开关,状态变为关闭
            System.out.println("Light is turned OFF");
            isOn = false;
        } else {
        // 关闭状态按下开关,状态变为开启
            System.out.println("Light is turned ON");
            isOn = true;
        }
    }
}

存在问题

如果电灯添加新的状态,则需要修改toggleSwitch()的逻辑,这种方式的两个弊端 :

  • 如果状态很多,条件语句会越来越多,会导致方法复杂,使代码难以理解和维护;
  • 每次添加状态都需要修改方法,可能会影响现有的状态切换逻辑,容易引入错误 。

新增状态代码实现

假设我们为电灯添加一个新状态,成为调光(Dim)状态,该种状态下 ,电灯的亮度比较低,但仍然是开启状态。

代码语言:Java复制
class Light {
    private boolean isOn;
    // 新增调光Dim状态
    private boolean isDim;

    public Light() {
        this.isOn = false; // 初始状态为关
        this.isDim = false; // 初始不是调光状态
    }

    public void toggleSwitch() {

       // 增加状态后修改状态转换逻辑
        if (isOn) {
            if (isDim) {
                System.out.println("Light is turned OFF");
                isOn = false;
                isDim = false;
            } else {
                System.out.println("Light is turned Dim");
                isDim = true;
            }
        } else {
            System.out.println("Light is turned ON");
            isOn = true;
        }
    }
}

总结

可以看到,上述例子新增了一个状态,方法的复杂程度就上升了一个级别,如果新增的不是一个状态,而是五个,十个甚至百个呢,这种实现方案明显不是一个好的选择。因此,这种方案只适合状态比较少切换逻辑不是很复杂的情形。

方案二:状态模式实现

代码实现

1. 定义一个状态接口(或抽象类)

代码语言:Java复制
// 状态接口
interface State {
    void toggleSwitch(Light light);
}

2. 为每个具体状态创建实现类

代码语言:Java复制
// 具体状态类:灯关闭状态
class OffState implements State {
    @Override
    public void toggleSwitch(Light light) {
        System.out.println("Light is turned ON");
        light.setState(new OnState());
    }
}

// 具体状态类:灯打开状态
class OnState implements State {
    @Override
    public void toggleSwitch(Light light) {
        System.out.println("Light is turned Dim");
        light.setState(new DimState());
    }
}

// 具体状态类:灯调光状态
class DimState implements State {
    @Override
    public void toggleSwitch(Light light) {
        System.out.println("Light is turned OFF");
        light.setState(new OffState());
    }
}

3.电灯将根据当前状态委托相关操作给状态对象

代码语言:Java复制
// 环境类,电灯
class Light {
    private State state;

    public Light() {
        // 初始状态为关
        this.state = new OffState();
    }

    public void setState(State state) {
        this.state = state;
    }

    public void toggleSwitch() {
        state.toggleSwitch(this);
    }
}

类图

总结

可以看到,采用状态模式添加新状态代码复杂度大大降低,只需要创建新的实现类并实现 State接口,然后在合适的位置进行状态切换即可。这种设计避免了复杂的条件语句,使代码更加清晰、可维护和可扩展。

状态模式

什么是状态模式

状态模式是一种行为设计模式, 让你能在一个对象的内部状态变化时改变其行为,使其看上去就像改变了自身所属的类一样。

状态模式核心概念

  • State(状态):定义一个接口或抽象类,用于封装与上下文相关的行为。
  • ConcreteState(具体状态):实现状态接口或继承抽象状态类,具体定义每个状态下的行为。
  • Context(上下文):维护一个状态对象,并在状态发生变化时改变其行为。
状态模式结构状态模式结构

优缺点

优点

  • 单一职责原则。 将与特定状态相关的代码放在单独的类中。
  • 开闭原则。 无需修改已有状态类和上下文就能引入新状态。
  • 通过消除臃肿的状态机条件语句简化上下文代码。

缺点

如果只有很少的几个状态, 或者很少发生改变, 那么应用该模式可能会显得小题大作。

参考资料

https://refactoringguru.cn/design-patterns/state


我正在参与2024腾讯技术创作特训营最新征文,快来和我瓜分大奖!

0 人点赞