状态模式并不是很常用,但是在能够用到的场景里,它可以发挥很大的作用。
状态设计模式是一种行为型设计模式,它允许对象在其内部状态发生变化时改变其行为。这种模式可以消除大量的条件语句,并将每个状态的行为封装到单独的类中。
状态模式的主要组成部分如下:
- 上下文(Context):上下文通常包含一个具体状态的引用,用于维护当前状态。上下文委托给当前状态对象处理状态相关行为。
- 抽象状态(State):定义一个接口,用于封装与上下文的特定状态相关的行为。
- 具体状态(Concrete State):实现抽象状态接口,为具体状态定义行为。每个具体状态类对应一个状态。
现在来看一个简单的 Java 示例。假设要模拟一个简易的电视遥控器,具有开启、关闭和调整音量的功能。
如果不使用设计模式,编写出来的代码可能是这个样子的,我们需要针对电视机当前的状态为每一次操作编写判断逻辑:
public class TV {
private boolean isOn;
private int volume;
public TV() {
isOn = false;
volume = 0;
}
public void turnOn() {
// 如果是开启状态
if (isOn) {
System.out.println("TV is already on.");
// 否则打开电视
} else {
isOn = true;
System.out.println("Turning on the TV.");
}
}
public void turnOff() {
if (isOn) {
isOn = false;
System.out.println("Turning off the TV.");
} else {
System.out.println("TV is already off.");
}
}
public void adjustVolume(int volume) {
if (isOn) {
this.volume = volume;
System.out.println("Adjusting volume to: " + volume);
} else {
System.out.println("Cannot adjust volume, TV is off.");
}
}
}
public class Main {
public static void main(String[] args) {
TV tv = new TV();
tv.turnOn();
tv.adjustVolume(10);
tv.turnOff();
}
}
当然在该例子中状态比较少,所以代码看起来也不是很复杂,但是状态如果变多了呢?比如加入换台,快捷键、静音等功能后呢?你会发现条件分支会急速膨胀,所以此时状态设计模式就要登场了
首先,定义抽象状态接口 TVState
,将每一个修改状态的动作抽象成一个接口:
public interface TVState {
void turnOn();
void turnOff();
void adjustVolume(int volume);
}
接下来,为每个具体状态创建类,实现 TVState
接口。例如,创建 TVOnState
和 TVOffState
类:
// 在on状态下,去执行以下各种操作
public class TVOnState implements TVState {
@Override
public void turnOn() {
System.out.println("TV is already on.");
}
@Override
public void turnOff() {
System.out.println("Turning off the TV.");
}
@Override
public void adjustVolume(int volume) {
System.out.println("Adjusting volume to: " + volume);
}
}
// 在关机的状态下执行以下的操作
public class TVOffState implements TVState {
@Override
public void turnOn() {
System.out.println("Turning on the TV.");
}
@Override
public void turnOff() {
System.out.println("TV is already off.");
}
@Override
public void adjustVolume(int volume) {
System.out.println("Cannot adjust volume, TV is off.");
}
}
接下来,定义上下文类 TV
:
public class TV {
// 当前状态
private TVState state;
public TV() {
state = new TVOffState();
}
public void setState(TVState state) {
this.state = state;
}
public void turnOn() {
// 打开
state.turnOn();
// 设置为开机状态
setState(new TVOnState());
}
public void turnOff() {
// 关闭
state.turnOff();
// 设置为关机状态
setState(new TVOffState());
}
public void adjustVolume(int volume) {
state.adjustVolume(volume);
}
}
最后,我们可以通过以下方式使用这些类:
public class Main {
public static void main(String[] args) {
TV tv = new TV();
tv.turnOn();
tv.adjustVolume(10);
tv.turnOff();
}
}
这个例子展示了状态模式的基本结构和用法。通过使用状态模式,我们可以更好地组织和管理与特定状态相关的代码。当状态较多时,这种模式的优势就会凸显出来,同时我们在代码时,因为我们会对每个状态进行独立封装,所以也会简化代码编写。