1 概述
定义 当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。
状态模式的核心是封装,状态的变更引起了行为的变更,从外部看起来就好像这个对象对应的类发生了改变一样。通用类图如下:
state 抽象状态角色:接口或抽象类,负责对象状态的定义,并且封装环境以实现状态切换。
concretestate 具体状态角色:负责本状态的行为和趋向状态的过渡处理
context 环境角色:定义客户端需要的接口,并负责具体状态的切换
2 代码示例
定义状态抽象类和具体状态类
/**
* @author chiangtaol
* @date 2020-12-09
* @describe 状态抽象类
*/
public abstract class StateAbstract {
/** 环境角色,提供给子类访问*/
protected Context context;
public void setContext(Context context){
this.context = context;
}
/** 行为1*/
public abstract void handler1();
/** 行为2*/
public abstract void handler2();
/** 行为3*/
public abstract void handler3();
}
/**
* @author chiangtaol
* @date 2020-12-09
* @describe 状态1
*/
public class State1 extends StateAbstract{
/**
* 行为1
*/
@Override
public void handler1() {
System.out.println("行为1触发...");
}
/**
* 行为2
*/
@Override
public void handler2() {
// 设置当前状态为2
super.context.setCurrentState(Context.STATE_2);
// 交由context去执行委托给具体的实现类
super.context.handle2();
}
/**
* 行为3
*/
@Override
public void handler3() {
// 规定不能由1-3
System.out.println("违规操作:不能1状态下执行行为3");
}
}
/**
* @author chiangtaol
* @date 2020-12-09
* @describe 状态2
*/
public class State2 extends StateAbstract{
/**
* 行为1
*/
@Override
public void handler1() {
// 规定不能由2-1
System.out.println("违规操作:不能2状态下执行行为1");
}
/**
* 行为2
*/
@Override
public void handler2() {
System.out.println("行为2触发...");
}
/**
* 行为3
*/
@Override
public void handler3() {
// 修改状态
super.context.setCurrentState(Context.STATE_3);
// 交给context去执行,委托给对应的实现类
super.context.handle3();
}
}
/**
* @author chiangtaol
* @date 2020-12-09
* @describe 状态3
*/
public class State3 extends StateAbstract{
/**
* 行为1
*/
@Override
public void handler1() {
// 改变状态
super.context.setCurrentState(Context.STATE_1);
super.context.handle1();
}
/**
* 行为2
*/
@Override
public void handler2() {
// 规定不能由3-2
System.out.println("违规操作:不能3状态下执行行为2");
}
/**
* 行为3
*/
@Override
public void handler3() {
System.out.println("行为3触发...");
}
}
定义场景类
/**
* @author chiangtaol
* @date 2020-12-09
* @describe 环境角色
*/
public class Context {
public final static StateAbstract STATE_1 = new State1();
public final static StateAbstract STATE_2 = new State2();
public final static StateAbstract STATE_3 = new State3();
/**
* 当前状态
*/
private StateAbstract currentState;
public StateAbstract getCurrentState() {
return currentState;
}
public void setCurrentState(StateAbstract currentState) {
this.currentState = currentState;
// 切换状态
this.currentState.setContext(this);
}
// 声明行为,具体执行交给状态实现类
public void handle1() {
this.currentState.handler1();
}
public void handle2() {
this.currentState.handler2();
}
public void handle3() {
this.currentState.handler3();
}
}
测试代码
@Test
public void test(){
//初始化环境角色
Context context = new Context();
//设置初始状态
context.setCurrentState(Context.STATE_1);
context.handle3();
context.handle1();
context.handle2();
context.handle3();
}
//结果
//违规操作:不能1状态下执行行为3
//行为1触发...
//行为2触发...
//行为3触发...
3 优缺点
3.1 优点
结构清晰
遵循设计原则,每个状态都是一个子类
封装性很好,状态的变换放到类内部实现,外部调用不用知道如何实现
3.2 缺点
状态过多会引起类膨胀的问题
4 使用场景
行为会随着状态改变而改变的场景
条件、分支判断语句替换
对象状态改变时行为受到约束的情况下使用