状态模式
定义
也成为状态机模式,是允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类,属于行为型模式。
状态模式中类的行为友状态决定,不同的状态下有不同的行为。其意图是让一个对象在其内部改变的时候,其行为也随之改变。状态模式的核心是状态与行为绑定,不同的状态对应不同的行为。
适用情景
状态模式主要解决的是当控制一个对象状态的条件表达式过去复杂时的情况。通过把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。对象的行为依赖于它的状态(属性),并且会根据它的状态改变二改变它的相关行为。
- 行为随状态改变而改变的场景。
- 一个操作中含有庞大的多分支结构,并且这些分支取决于对象的状态。
角色
- 环境类角色:定义客户端需要的接口,内部维护一个当前状态实例。并负责具体状态的切换。
- 抽象状态:定义该状态下的行为,可以有一个或多个行为。
- 具体状态:具体实现该状态对应的行为,并且在需要的情况下进行状态切换。
实例
public abstract class UserState {
protected AppContext appContext;
public void setAppContext(AppContext appContext) {
this.appContext = appContext;
}
public abstract void favorite();
public abstract void comment(String comment);
}
public class AppContext {
public static final UserState STATE_LOGIN = new LoginState();
public static final UserState STATE_UNLOGIN = new UnLoginState();
private UserState currentState = STATE_UNLOGIN;
{
STATE_LOGIN.setAppContext(this);
STATE_UNLOGIN.setAppContext(this);
}
public void setState(UserState state){
this.currentState = state;
this.currentState.setAppContext(this);
}
public UserState getState(){
return this.currentState;
}
public void favorite(){
this.currentState.favorite();
}
public void comment(String comment){
this.currentState.comment(comment);
}
}
public class LoginState extends UserState{
public void favorite() {
System.out.println("收藏成功");
}
public void comment(String comment) {
System.out.println(comment);
}
}
public class UnLoginState extends UserState{
public void favorite() {
this.switch2Login();
this.appContext.getState().favorite();
}
public void comment(String comment) {
this.switch2Login();
this.appContext.getState().comment(comment);
}
private void switch2Login(){
System.out.println("跳转到登录页面");
this.appContext.setState(this.appContext.STATE_LOGIN);
}
}
public class test {
public static void main(String[] args) {
AppContext appContext = new AppContext();
appContext.favorite();
appContext.comment("000");
}
}
状态模式相关的设计模式
1. 状态模式与责任链模式
状态模式和责任链模式都能消除if分支过多的问题。但某些情况下,状态模式中的状态可以理解为责任,那么这种情况下,两种模式都可以使用。
从状态来看,状态模式强调的是一个对象内在状态的改变,二责任模式强调的是外部结点对象见的改变。
从其代码实现上来看,它们间最大的区别就是状态模式各个状态对象知道自己下一个要进入的状态对象。而责任链模式并不清楚其下一个结点处理对像。
2. 状态模式与策略模式
状态模式与策略模式的UML类图架构几乎一样,但是它们的应用场景不同。策略模式多种算法行为选择其中一个都能满足,彼此间是独立的,用户可自行更换策略算法;而状态模式各个状态间是存在相互关系的,彼此之间在一定条件下存在自动切换效果。且用户无法指定状态,只能设置初始状态。
优点
- 结构清晰,将状态独立为类,消除冗余的if…else… 或switch…case语句,使代码更加简洁,提高系统可维护性;
- 将状态转化显示化:通常的对象内部都是使用数值类型定义状态,状态的切换是通过赋值进行表现,不够直观;而使用状态类,在切换状态时,是以不同的类进行表示,转换目的更加明确;
- 状态类职责明确且具备扩展性。
缺点
- 类膨胀:如果一个事物具有很多状态,则会造成状态类太多。
- 状态模式的结构与实现较为复杂,如果使用不当将导致程序结构和代码混乱。
- 状态模式对开闭原则的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的类的源码。否则无法切换到新的状态,而且修改某个状态类的行为也需要修改对应类的源代码。