状态模式
状态模式(State Pattern)属于行为型模式。它是允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。
状态模式中类的行为是由状态决定的,不同的状态下有不同的行为。其意图是让一个对象在其内部改变的时候,其行为也随之改变。状态模式核心是状态与行为绑定,不同的状态对应不同的行为。
状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况。通过把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。对象的行为依赖于它的状态属性,并且会根据它的状态改变而改变它的相关行为。
应用场景
1.行为随状态改变而改变的场景
2.一个操作中含有庞大的多分支结构,并且这些分支取决于对象的状态。
例如:订单信息的变化、快递信息的变化、文档的审核状态变化。
假如有一个 文档Document类。 文档可能会处于
草稿Draft 、审阅中Moderation和已发布Published
三种状态中的一种。 文档的publish发布方法在不同状态下的行为略有不同:
草稿状态时, 它会将文档转移到审阅中状态。
审阅中状态时, 如果当前用户是管理员, 它会公开发布文档。
已发布状态时, 它不会进行任何操作。
优缺点
优点:
1.结构清晰:将状态独立为类,封装转换规则。消除冗余的if.else或switch...case语句,使代码更加简洁,提高系统可维护性。
2.将状态转换显示化:通常对象内部都是使用数值类型来定义状态,状态的切换是通过赋值进行表现,不够直观。而使用状态类,在切换状态时,是以不同的类进行表示,转换目的更加明确。
3.将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
缺点:
1.类膨胀:如果一个事物具备很多状态,必然会增加系统类和对象的个数,会造成状态类太多
2.状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱
3.状态模式对开闭原则的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应源码。
主要角色
1.环境类角色(Context)
定义客户端需要的接口,内部维护一个当前状态实例,并负责具体状态的切换。
2.抽象状态角色(Sate)
定义该状态下的行为,可以有一个或多个行为。
3.具体状态角色(ConcreteState)
具体实现该状态对应的行为,并且在需要的情况下进行状态切换。
状态模式的基本使用
创建抽象状态角色
抽象状态角色,定义该状态下的行为,可以有一个或多个行为
public abstract class State {
protected Context context;
public void setContext(Context context) {
this.context = context;
}
/**
* 一个行为
*/
public abstract void action();
}
创建具体状态角色
创建具体状态角色,具体实现该状态对应的行为,并且在需要的情况下进行状态切换
public class ConcreteStateA extends State {
@Override
public void action() {
if (Math.random() > 0.5) {
System.out.println("ConcreteStateA执行成功,继续执行!");
// 行为状态自动切换
this.context.setState(Context.STATE_B);
this.context.getState().action();
} else {
System.out.println("ConcreteStateA执行完成");
}
}
}
public class ConcreteStateB extends State {
@Override
public void action() {
if (Math.random() > 0.5) {
System.out.println("ConcreteStateB执行成功,继续执行!");
// 行为状态自动切换
this.context.setState(Context.STATE_C);
this.context.getState().action();
} else {
System.out.println("ConcreteStateB执行完成");
}
}
}
public class ConcreteStateC extends State {
@Override
public void action() {
System.out.println("ConcreteStateC执行完成");
}
}
创建环境类角色
创建环境类角色,定义客户端需要的接口,内部维护一个当前状态实例,并负责具体状态的切换。
public class Context {
public static final State STATE_A = new ConcreteStateA();
public static final State STATE_B = new ConcreteStateB();
public static final State STATE_C = new ConcreteStateC();
/**
* 默认状态
*/
private State defaultState = STATE_A;
{
STATE_A.setContext(this);
STATE_B.setContext(this);
STATE_C.setContext(this);
}
public void setState(State state) {
this.defaultState = state;
this.defaultState.setContext(this);
}
public State getState() {
return this.defaultState;
}
public void doAction() {
this.defaultState.action();
}
}
客户端执行
public static void main(String[] args) {
System.out.println("---------从状态A开始执行---------");
Context context = new Context();
context.doAction();
System.out.println("---------从状态B开始执行---------");
context.setState(new ConcreteStateB());
context.doAction();
}
---------从状态A开始执行---------
ConcreteStateA执行成功,继续执行!
ConcreteStateB执行成功,继续执行!
ConcreteStateC执行完成
---------从状态B开始执行---------
ConcreteStateB执行成功,继续执行!
ConcreteStateC执行完成
标签:状态,STATE,模式,State,context,设计模式,行为,public
From: https://blog.51cto.com/chencoding/5711157