设计模式之状态模式
定义
允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。
类似于我们商城下单,订单有各种状态,不同的状态下可以执行不同的操作。
结构
- State,状态接口,用来封装与上下文的一个特定状态所对应的行为。
- ConcreteState,具体状态实现类,提供对应状态的具体行为处理。
- Context,上下文,内部维护一个当前状态,并负责具体状态的切换。
简单实现
状态接口
public interface State {
void handle(Context context);
}
具体状态实现类
public class ConcreteStateA implements State {
@Override
public void handle(Context context) {
System.out.println("当前状态:A");
//状态 A 执行完后,迁移到状态 B
context.setState(new ConcreteStateB());
}
}
另一个具体状态实现
public class ConcreteStateB implements State {
@Override
public void handle(Context context) {
System.out.println("当前状态:B");
//状态 B 执行完后,迁移到状态 A
context.setState(new ConcreteStateA());
}
}
上下文
public class Context {
private State state;
public Context(State state) {
this.state = state;
}
public void handle() {
// 注意:这里传入当前对象
state.handle(this);
}
public State getState() {
return state;
}
public Context setState(State state) {
this.state = state;
return this;
}
}
客户端
public class Client {
public static void main(String[] args) {
Context context = new Context(new ConcreteStateA());
context.handle();
context.handle();
context.handle();
context.handle();
context.handle();
}
}
状态模式在JSF中的实现
JSF 是一种用于构建Java Web 应用程序的标准框架。
引入maven依赖
<dependency>
<groupId>javax.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>2.2.20</version>
</dependency>
示例
JSF中的FacesContext,PhaseId
public class PhaseId implements Comparable {
...
private static final PhaseId[] values = {
ANY_PHASE, // 任意一个生命周期阶段
RESTORE_VIEW, // 恢复视图阶段
APPLY_REQUEST_VALUES, // 应用请求值阶段
PROCESS_VALIDATIONS, // 处理输入校验阶段
UPDATE_MODEL_VALUES, // 更新模型的值阶段
INVOKE_APPLICATION, // 调用应用阶段
RENDER_RESPONSE // 显示响应阶段
};
...
}
FacesContext中保存一个阶段对象
public class FacesContextImpl extends FacesContext {
private PhaseId currentPhaseId;
}
总结
优点
- 简化应用逻辑控制,使用单独的类来封装一个状态的处理,分离了状态和行为的处理。
- 更好的扩展性,很容易新增状态类的实现。
缺点
- 一个状态对应一个状态处理类,会导致类的数量过多,程序复杂。
本质
状态模式的本质是根据状态来分离和选择行为,通过接口分离了状态和行为,通过上下文来选择行为。
使用场景
- 一个对象的行为取决于它的状态,并且必须在运行时根据状态来改变它的行为。
- 一个操作中包含大量的分支语句,且这些分支依赖于该对象的状态,可以将各分支的处理封装到单独的状态处理类中。
参考
大战设计模式【14】—— 状态模式
设计模式——状态模式
状态模式(详解版)
设计模式(二十二)——状态模式(APP抽奖活动+借贷平台源码剖析)
研磨设计模式-书籍