引入
试着思考下这个功能如何实现:电灯有两种状态:开启(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腾讯技术创作特训营最新征文,快来和我瓜分大奖!