一、概述
允许一个对象在其内部状态改变时,改变它的行为
在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象。
注意事项:在行为受状态约束的时候使用状态模式,而且状态不超过 5 个。
1.1、适用场景
一个对象存在多个状态(不同状态下行为不同),且状态可相互转换.
比如:电商订单状态扭转等
状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转译到表现不同状态的一系列类当中,可以把复杂的判断逻辑简化。
简单来说:
1.2、优缺点
优点: 1、封装了转换规则。 2、枚举可能的状态,在枚举状态之前需要确定状态种类。 3、将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。 4、允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。 5、可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
缺点: 1、状态模式的使用必然会增加系统类和对象的个数。 2、状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。 3、状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。
1.3、类图角色及其职责
Context:它就是那个含有状态的对象,它可以处理一些请求,这些请求最终产生的响应会与状态相关。
State:状态接口,它定义了每一个状态的行为集合,这些行为会在Context中得以使用。
ConcreteState:具体状态,实现相关行为的具体状态类。
1.4、演进过程
创建一个接口
public interface State{ void doAction (Context context); }
创建 Context 类
public class Context { private State state; public Context(){ state = null; } public void setState(State state){ this.state = state; } public State getState(){ return state; } }
创建实现接口的实体类。
public class LogInState implements State { @Override public void doAction (Context context){ System.out.println("登陆成功"); } }
public class LogOutState implements State { @Override public void doAction (Context context){ System.out.println("退出成功"); } }
测试
使用 Context 来查看当状态 State 改变时的行为变化。
@Test public void test() { Context context = new Context(); LogInState startState = new LogInState(); startState.doAction(context); LogOutState stopState = new LogOutState(); stopState.doAction(context); }
输出
登陆成功
退出成功
二、扩展
javax.faces.lifecycle.Lifecycle、javax.faces.webapp.FacesServlet