设计模式 - 浅谈状态模式
状态模式
模式功能说明:它允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
模式思路与原理
状态模式的主要角色:抽象状态角色(State
) 、具体状态角色(ConcreteState
)、环境角色(Context
)。
代码示例
interface State {
void handle(Context context);
}
class ConcreteStateA implements State {
public void handle(Context context) {
System.out.println("当前状态是 A.");
context.setState(new ConcreteStateB());
}
}
class ConcreteStateB implements State {
public void handle(Context context) {
System.out.println("当前状态是 B.");
context.setState(new ConcreteStateA());
}
}
class Context {
private State state;
public Context(State state) {
this.state = state;
}
public void setState(State state) {
this.state = state;
}
public void request() {
state.handle(this);
}
}
public class StatePatternDemo {
public static void main(String[] args) {
Context context = new Context(new ConcreteStateA());
context.request();
context.request();
}
}
我们定义了一个Context
类,它有一个State
类型的成员变量,表示当前的状态。我们还定义了两个具体的状态类ConcreteStateA
和ConcreteStateB
,它们都实现了State
接口,表示它们都有处理请求的能力。在ConcreteStateA
中,处理请求后,会将状态切换为ConcreteStateB
;在ConcreteStateB
中,处理请求后,会将状态切换为ConcreteStateA
。这样,我们就可以通过调用Context
的request
方法来不断地在两个状态之间切换。
使用场景:
- 当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。
- 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。
优缺点
优点:
- 封装了转换规则,并且枚举可能的状态,在状态模式中定义了状态转换的规则,消除了庞大的条件分支语句。
- 将所有与某个状态有关的行为放到一个类中,只需要注入一个不同的状态对象即可使系统处于不同的状态。
- 允许状态转换逻辑与状态对象合成一体,而不是放置在主体类中。
缺点:
- 状态模式的使用必然会增加系统的类和对象的个数。
- 状态模式的结构和实现比较复杂,如果使用不当会导致程序结构和代码的混乱。
总结
状态模式实现了设计原则中的“开闭原则”,即对扩展开放,对修改关闭。在状态模式中,我们可以通过添加新的状态类来增加新的状态和转换,而不是修改已有的代码。 状态模式主要用来解决对象在多种状态转换时,避免大量的条件判断,使得状态的转换更加明确,且更易于维护和扩展。但是使用状态模式会增加系统的类和对象的个数,且状态模式的结构和实现比较复杂。