状态模式
当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
上面是百度百科的解释,看起来有点难以理解其实可以理解为:它说当状态改变时,这个对象的行为也会变,而看起来就像是这个类改变了一样。
类结构图
Context
含有状态的类,维护一个 State 的实例。
State
状态接口。抽象状态类,定义一个接口以封装与 Context 的的一个状态相关的行为。
ConcreteState
具体的状态类。
代码示例
public interface State {
void handle();
}
public class ConcreteStateA implements State {
@Override
public void handle() {
System.out.println("State 状态 A 的处理逻辑!");
}
}
public class ConcreteStateB implements State {
@Override
public void handle() {
System.out.println("State 状态 B 的处理逻辑!");
}
}
public class Context {
public static final State STATE_A = new ConcreteStateA();
public static final State STATE_B = new ConcreteStateB();
private State state = STATE_A;
public void setState(State state) {
this.state = state;
}
public void execute() {
this.state.handle();
}
}
客户端示例
public class Client {
public static void main(String[] args) {
// 默认状态 A
Context context = new Context();
context.execute();
// 切换为状态 B
context.setState(Context.STATE_B);
context.execute();
// 再切换为状态 A
context.setState(Context.STATE_A);
context.execute();
}
}
运行结果
Connected to the target VM, address: '127.0.0.1:58526', transport: 'socket'
State 状态 A 的处理逻辑!
State 状态 B 的处理逻辑!
State 状态 A 的处理逻辑!
Disconnected from the target VM, address: '127.0.0.1:58526', transport: 'socket'
Process finished with exit code 0
什么时候考虑使用状态模式?
当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。
如果某项业务有多个状态,通常是一些枚举、常量,状态的变化都是靠大量 if 分支判断语句来实现,此时应该考虑将业务状态定义为一个 State 的子类。
优点
将与特定状态相关的行为局部化,并且将不同的状态的行为分割开来。
缺点
- 状态模式的使用必然会增加系统类和对象的个数。
- 状态模式对“开闭原则”的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态;而且修改某个状态类的行为也需修改对应类的源代码。