状态模式(State Pattern)
状态模式(State Pattern)是一种行为设计模式,它允许对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。以下从多个方面详细介绍状态模式。
模式结构与角色
状态模式主要包含以下几个角色:
- 抽象状态(State):定义了一个接口,封装了与上下文的一个特定状态相关的行为。通常包含多个方法,这些方法对应着上下文在该状态下可能执行的操作。
- 具体状态(Concrete State):实现了抽象状态接口,每个具体状态类都封装了特定状态下的行为逻辑。当上下文的状态改变时,会委托给相应的具体状态类来处理。
- 上下文(Context):维护一个对抽象状态对象的引用,负责根据业务逻辑切换状态。上下文将请求委托给当前的状态对象来处理。
代码示例
以下是一个简单的状态模式示例,模拟一个电梯系统,电梯有开门、关门、运行、停止四种状态:
// 抽象状态
interface ElevatorState {
void open();
void close();
void run();
void stop();
}
// 具体状态:开门状态
class OpenState implements ElevatorState {
private Elevator elevator;
public OpenState(Elevator elevator) {
this.elevator = elevator;
}
@Override
public void open() {
System.out.println("电梯已经开门,无需重复开门");
}
@Override
public void close() {
System.out.println("电梯门关闭");
elevator.setState(elevator.getCloseState());
}
@Override
public void run() {
System.out.println("电梯门未关闭,不能运行");
}
@Override
public void stop() {
System.out.println("电梯已经开门,处于停止状态");
}
}
// 具体状态:关门状态
class CloseState implements ElevatorState {
private Elevator elevator;
public CloseState(Elevator elevator) {
this.elevator = elevator;
}
@Override
public void open() {
System.out.println("电梯门打开");
elevator.setState(elevator.getOpenState());
}
@Override
public void close() {
System.out.println("电梯门已经关闭,无需重复关门");
}
@Override
public void run() {
System.out.println("电梯开始运行");
elevator.setState(elevator.getRunState());
}
@Override
public void stop() {
System.out.println("电梯还未运行,无需停止");
}
}
// 具体状态:运行状态
class RunState implements ElevatorState {
private Elevator elevator;
public RunState(Elevator elevator) {
this.elevator = elevator;
}
@Override
public void open() {
System.out.println("电梯正在运行,不能开门");
}
@Override
public void close() {
System.out.println("电梯正在运行,门已经关闭");
}
@Override
public void run() {
System.out.println("电梯正在运行,无需重复启动");
}
@Override
public void stop() {
System.out.println("电梯停止运行");
elevator.setState(elevator.getStopState());
}
}
// 具体状态:停止状态
class StopState implements ElevatorState {
private Elevator elevator;
public StopState(Elevator elevator) {
this.elevator = elevator;
}
@Override
public void open() {
System.out.println("电梯门打开");
elevator.setState(elevator.getOpenState());
}
@Override
public void close() {
System.out.println("电梯门已经关闭,无需重复关门");
}
@Override
public void run() {
System.out.println("电梯开始运行");
elevator.setState(elevator.getRunState());
}
@Override
public void stop() {
System.out.println("电梯已经停止,无需重复停止");
}
}
// 上下文:电梯
class Elevator {
private ElevatorState openState;
private ElevatorState closeState;
private ElevatorState runState;
private ElevatorState stopState;
private ElevatorState currentState;
public Elevator() {
openState = new OpenState(this);
closeState = new CloseState(this);
runState = new RunState(this);
stopState = new StopState(this);
currentState = closeState;
}
public ElevatorState getOpenState() {
return openState;
}
public ElevatorState getCloseState() {
return closeState;
}
public ElevatorState getRunState() {
return runState;
}
public ElevatorState getStopState() {
return stopState;
}
public void setState(ElevatorState state) {
this.currentState = state;
}
public void open() {
currentState.open();
}
public void close() {
currentState.close();
}
public void run() {
currentState.run();
}
public void stop() {
currentState.stop();
}
}
// 客户端代码
public class StatePatternExample {
public static void main(String[] args) {
Elevator elevator = new Elevator();
elevator.open();
elevator.close();
elevator.run();
elevator.stop();
elevator.open();
}
}
代码解释
- 抽象状态
ElevatorState
:定义了电梯的四个操作方法open()
、close()
、run()
和stop()
,具体状态类需要实现这些方法。 - 具体状态类(
OpenState
、CloseState
、RunState
、StopState
):实现了ElevatorState
接口,每个类都封装了电梯在相应状态下的行为逻辑,并且在合适的操作后会改变电梯的状态。 - 上下文
Elevator
:维护了四个具体状态对象的引用,以及当前的状态currentState
。通过setState()
方法可以切换状态,并且将电梯的操作委托给当前状态对象来处理。 - 客户端代码:创建了电梯对象,并依次调用电梯的开门、关门、运行、停止和开门操作,观察电梯在不同状态下的行为。
优点
- 可维护性和可扩展性:将不同状态的行为封装在各自的具体状态类中,使得代码结构清晰,易于维护。当需要添加新的状态时,只需要创建新的具体状态类,符合开闭原则。
- 消除条件判断:避免了使用大量的
if - else
或switch - case
语句来处理不同状态的情况,使代码更加简洁和可读。 - 状态转换清晰:状态模式明确了状态之间的转换关系,每个状态类只负责自己状态下的行为和状态转换逻辑,使状态转换更加清晰和易于理解。
缺点
- 类的数量增加:随着状态的增加,具体状态类的数量也会增加,导致系统中的类数量增多,增加了系统的复杂度。
- 状态之间的耦合:如果状态之间的转换逻辑比较复杂,可能会导致具体状态类之间存在一定的耦合,影响代码的可维护性。
应用场景
- 工作流管理:在工作流系统中,任务可能有不同的状态(如待审批、已审批、已完成等),状态模式可以方便地管理任务在不同状态下的行为和状态转换。
- 游戏开发:游戏中的角色或物体可能有不同的状态(如站立、行走、攻击、防御等),使用状态模式可以实现角色在不同状态下的行为逻辑。
- 设备控制:对于一些复杂的设备,如电梯、自动售货机等,设备有不同的工作状态,状态模式可以有效地管理设备在不同状态下的操作和状态转换。
Java设计模式 文章被收录于专栏
设计模式是软件开发中针对反复出现的问题所总结归纳出的通用解决方案,它可以帮助开发者更高效地构建软件系统,提升代码的可维护性、可扩展性和可复用性。