定义:
允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
状态模式把所研究的对象的行为包装在不同的状态对象里,每一个状态对象都属于一个抽象状态类的一个子类。状态模式的意图是让一个对象在其内部状态改变的时候,其行为也随之改变。
图示:
● 环境(Context) (上下文):定义客户端所感兴趣的接口,并且保留一个具体状态类的实例。这个具体状态类的实例给出此环境对象的现有状态。
● 抽象状态(State) :定义一个接口,用以封装环境(Context)对象的一个特定的状态所对应的行为。
● 具体状态(ConcreteState):每一个具体状态类都实现了环境(Context)的一个状态所对应的行为。
框架示例:
public class Context {
//持有一个State类型的对象实例
private State state;
public void setState(State state) {
this.state = state;
}
/**
* 用户感兴趣的接口方法
*/
public void request(String sampleParameter) {
//转调state来处理
state.handle(sampleParameter);
}
}
public interface State {
/**
* 状态对应的处理
*/
public void handle(String sampleParameter);
}
public class ConcreteStateA implements State {
@Override
public void handle(String sampleParameter) {
System.out.println("ConcreteStateA handle :" + sampleParameter);
}
}
public class ConcreteStateB implements State {
@Override
public void handle(String sampleParameter) {
System.out.println("ConcreteStateB handle :" + sampleParameter);
}
}
public class Client {
public static void main(String[] args){
//创建状态
State state = new ConcreteStateB();
//创建环境
Context context = new Context();
//将状态设置到环境中
context.setState(state);
//请求
context.request("test");
}
}
在状态模式中,环境(Context)是持有状态的对象,但是环境(Context)自身并不处理跟状态相关的行为,而是把处理状态的功能委托给了状态对应的状态处理类来处理。在具体的状态处理类中经常需要获取环境(Context)自身的数据,甚至在必要的时候会回调环境(Context)的方法,因此,通常将环境(Context)自身当作一个参数传递给具体的状态处理类。
客户端一般只和环境(Context)交互。客户端可以用状态对象来配置一个环境(Context),一旦配置完毕,就不再需要和状态对象打交道了。客户端通常不负责运行期间状态的维护,也不负责决定后续到底使用哪一个具体的状态处理对象。
一个简单示例:
public abstract class FlowState {
protected Context context;
public void setContext(Context context) {
this.context = context;
}
abstract void audit();
abstract void pass();
abstract void noPass();
}
public class Audit extends FlowState{
@Override
void audit() {
System.out.println("审核中...");
}
@Override
void pass() {
super.context.setState(Context.PASS);
super.context.getState().pass();
}
@Override
void noPass() {
super.context.setState(Context.NO_PASS);
super.context.getState().noPass();
}
}
public class Pass extends FlowState{
@Override
void audit() {
super.context.setState(Context.AUDIT);
super.context.getState().audit();
}
@Override
void pass() {
System.out.println("通过啦...");
}
@Override
void noPass() {
super.context.setState(Context.NO_PASS);
super.context.getState().noPass();
}
}
public class NoPass extends FlowState{
@Override
void audit() {
super.context.setState(Context.AUDIT);
super.context.getState().audit();
}
@Override
void pass() {
super.context.setState(Context.PASS);
super.context.getState().pass();
}
@Override
void noPass() {
System.out.println("不通过...");
}
}
public class Context {
protected FlowState state;
protected static final Audit AUDIT = new Audit();
protected static final NoPass NO_PASS = new NoPass();
protected static final Pass PASS = new Pass();
public Context(FlowState state) {
setState(state);
}
public FlowState getState() {
return state;
}
public void setState(FlowState state) {
this.state = state;
this.state.setContext(this);
}
void audit(){
this.getState().audit();
}
void pass(){
this.getState().pass();
}
void noPass(){
this.getState().noPass();
}
}
public class Apply {
public static void main(String[] args){
try {
//下属申请
System.out.println("提交申请...");
Context context = new Context(new Audit());
context.audit();
Thread.sleep(100);
//模拟上级看到申请后的动作
context.pass();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
总结:
状态模式的设计思想是把不同状态的逻辑分离到不同的状态类中,从而使得增加新状态更容易;状态模式的实现关键在于状态转换。简单的状态转换可以直接由调用方指定,复杂的状态转换可以在内部根据条件触发完成。