1、概述
状态模式是一种行为设计模式,它允许对象在其内部状态改变时改变其行为。这种模式主要用于实现对象之间的解耦,使得对象可以在不修改其结构的情况下改变其行为。
角色:
上下文(Context):负责维护当前状态和根据当前状态调用相应的状态处理方法。
状态(State):表示对象的状态,每个状态都有一个对应的处理方法。
具体状态(Concrete State):是状态的具体实现,继承自状态接口。
2、优缺点
优点:
1、封装了转换规则。
2、枚举可能的状态,在枚举状态之前需要确定状态种类。
3、将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
4、允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
5、可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
缺点:
1、状态模式的使用必然会增加系统类和对象的个数。
2、状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
3、状态模式对“开闭原则”的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态;而且修改某个状态类的行为也需修改对应类的源代码。
3、实现方式
// 应用程序
public class Test {
public static void main(String[] args) {
Elevator elevator = new Elevator();
elevator.openDoor(); // 输出:电梯门已打开
elevator.closeDoor(); // 输出:电梯门已关闭
elevator.goUp(); // 输出:电梯开始上升
elevator.closeDoor(); // 输出:电梯正在运行,无需关闭门
elevator.goDown(); // 输出:电梯继续下降
}
}
// 状态接口
interface State {
void openDoor();
void closeDoor();
void goUp();
void goDown();
}
// 停止状态
class StopState implements State {
private Elevator context;
public StopState(Elevator elevator) {
this.context = elevator;
}
@Override
public void openDoor() {
System.out.println("电梯门已打开");
}
@Override
public void closeDoor() {
System.out.println("电梯门已关闭");
}
@Override
public void goUp() {
System.out.println("电梯开始上升");
// 切换到运行状态
context.setState(new RunState(context));
}
@Override
public void goDown() {
System.out.println("电梯开始下降");
// 切换到运行状态
context.setState(new RunState(context));
}
}
// 运行状态
class RunState implements State {
private Elevator context;
public RunState(Elevator elevator) {
this.context = elevator;
}
@Override
public void openDoor() {
System.out.println("电梯正在运行,无法打开门");
}
@Override
public void closeDoor() {
System.out.println("电梯正在运行,无需关闭门");
}
@Override
public void goUp() {
System.out.println("电梯继续上升");
}
@Override
public void goDown() {
System.out.println("电梯继续下降");
}
}
// 故障状态
class FaultState implements State {
private Elevator context;
public FaultState(Elevator elevator) {
this.context = elevator;
}
@Override
public void openDoor() {
System.out.println("电梯故障,无法打开门");
}
@Override
public void closeDoor() {
System.out.println("电梯故障,无需关闭门");
}
@Override
public void goUp() {
System.out.println("电梯故障,无法上升");
}
@Override
public void goDown() {
System.out.println("电梯故障,无法下降");
}
}
// 电梯类
class Elevator {
private State state;
public Elevator() {
this.state = new StopState(this);
}
public void setState(State state) {
this.state = state;
}
public void openDoor() {
state.openDoor();
}
public void closeDoor() {
state.closeDoor();
}
public void goUp() {
state.goUp();
}
public void goDown() {
state.goDown();
}
}
4、应用场景
当一个对象的行为取决于它的状态,并且在运行时需要根据状态改变行为时,可以考虑使用状态模式。
当一个对象有多个状态,并且状态之间存在复杂的转换逻辑时,可以使用状态模式来简化代码和提高可维护性。
当需要避免使用大量的条件语句来控制对象的行为时,状态模式可以提供一种更加优雅的解决方案。