状态模式
在状态模式(State Pattern)中,类的行为是基于它的状态改变的。这种类型的设计模式属于行为型模式。
在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象。
当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类
介绍
意图:允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。
主要解决:对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为。
何时使用:代码中包含大量与对象状态有关的条件语句。
如何解决:将各种具体的状态类抽象出来。
1、有一个对象,它是有状态的。
2、这个对象在状态不同的时候,行为不一样。
3、这些状态是可以切换的,而非毫无关系。
前两点比较好理解,第3点有时候容易给人比较迷惑的感觉,什么叫这些状态是可以切换的,而非毫无关系?
举个例子,开关,可以互相转换。
关键代码:通常命令模式的接口中只有一个方法。而状态模式的接口中有一个或者多个方法。而且,状态模式的实现类的方法,一般返回值,或者是改变实例变量的值。也就是说,状态模式一般和对象的状态有关。实现类的方法有不同的功能,覆盖接口中的方法。状态模式和命令模式一样,也可以用于消除 if...else 等条件选择语句。
优点:
1:对状态转换规则进行了封装;
2:可以使用枚举类,枚举出所有可能的状态。但是需要在枚举状态之前确定状态的种类;
3:扩展性好。将所有与某个或者某些状态有关的行为放到了一个类对象中,这样方便管理,并且可以方便的新增状态,只需要改变对象状态就可以实现改变对象行为了;
4:代码简洁好维护。状态模式允许状态转换逻辑和状态对象合为一体,而不是一个巨大的条件语句块;
5:可以让多个不同的环境对象共享一个状态的对象,这样减少系统中对象的数量。
缺点:
1:增加对象和系统类的个数;
2:结构与实现比较复杂,如果使用不当,可能会造成程序结构和代码给人感觉很混乱的;
3:对开闭原则支持不好。
使用场景: 1、行为随状态改变而改变的场景。 2、条件、分支语句的代替者。
注意事项:在行为受状态约束的时候使用状态模式,而且状态不超过 5 个。
模式中的角色:
1 上下文环境(Context):它定义了客户程序需要的接口并维护一个具体状态角色的实例,将与状态相关的操作委托给当前的Concrete State对象来处理。
2 接口状态(State):定义一个接口以封装使用上下文环境的的一个特定状态相关的行为。
3 具体状态(Concrete State):实现抽象状态定义的接口。
实现
步骤 1
/* Context 是一个带有某个状态的类 */ public class Context { private State state; public Context() { state=null; } public State getState() { return state; } public void setState(State state) { this.state = state; } }
步骤 2
/* State 接口的实体状态类 */ public interface State { public void Action(Context context); public String getState(); }
步骤 3
/* 创建实现接口的实体类。 */ public class StartState implements State { @Override public void Action(Context context) { System.out.println("Player start"); context.setState(this); } public String getState(){ return "start"; } }
步骤 4
/* 创建实现接口的实体类。 */ public class StopState implements State { @Override public void Action(Context context) { System.out.println("Player Stop"); context.setState(this); } public String getState(){ return "Start"; } }
步骤 5
/* 状态模式(State Pattern) */ public class StatePatternDescription { public static void main(String[] args) { Context context = new Context(); StartState startState = new StartState(); startState.Action(context); System.out.println(context.getState().getState()); StopState stopState = new StopState(); stopState.Action(context); System.out.println(context.getState().getState()); } }
结果:
Player start
start
Player Stop
Start