概述
在状态模式中,状态通常指的是对象实例的某个属性值,而行为指的就是对象的方法。
它通过把状态和状态对应的行为分离开来,把所有与一个特定的状态相关的行为都放在一个对象中,通过维护状态的变化,来调用不同状态对应的方法。使得应用程序在控制的时候只需要关心状态的转换,而不用关心这个状态对应的真正处理。简而言之就是状态决定行为。
在状态模式中,上下文是持有状态的对象,但是上下文自己并不处理和状态相关的行为,而是把处理状态的功能委托给了状态对应的对象处理。一般而言上下文持有一个状态对象,以及状态维护,状态处理类负责状态的改变。当然状态的改变也可以放在上下文中
在具体的状态类处理类中经常需要获取上下文自身的数据,以及回调上下文的方法,因此通常情况下会将上下文作为一个参数传递给具体的状态处理类。
客户端一般只和上下文交互,并且一般不负责运行期间状态的维护,也不负责决定后续到底使用哪个具体的状态处理对象。
在状态模式中,状态的维护指的是维护状态的数据,给状态设置不同的状态值,而状态的转换指的是根据状态的变化选择不同的状态处理对象。
状态维护和转换控制
一般通常有如下几个地方可以进行状态的维护和转换控制:
1.上下文中,因为状态本身通常被实现为上下文对象的状态,因此可以在上下文中进行状态的维护和状态的转换。这种情况一般适用于状态转换规则相对固定,不需要进行什么扩展。
2.状态的处理类中:当每个状态处理对象处理完自身状态所对应的功能后,可以根据需要指定后继状态,一遍让应用能够正确处理后续的请求。
这种情况适用于当前状态取决于前一个状态动态处理的结果,或者是依赖于外部数据的情况
3.使用数据库或者文件:
这种方式可以通过在程序中查询数据库中的数据来得到状态编码,然后根据状态编码来创建出相应的状态对象,在委托相应的状态对象进行功能处理。
使用这种方式的话,还可以通过将状态码和状态处理类名存放到配置文件中,这样就可以直接通过配置文件获取到状态处理类的类名,再通过反射机制创建出处理类,这种方式的好处就在于上下文中状态转换维护的代码就相对固定。
状态扩展
状态模式的扩展只需要新增一个实现状态处理的公共接口实现类,然后在进行状态维护的地方,设置状态变化到这个新的状态即可。
public interface State { public void someOperation(); }
|
public class ConcreStateOne implements State{ private Context mContext = null; public ConcreStateOne(Context context) { mContext = context; } public void someOperation() { System.out.println("This is from ConcreStateOne"); mContext.changeStateCode(2); } }
|
public class ConcreStateTwo implements State{ private Context mContext = null; public ConcreStateTwo(Context context) { mContext = context; } public void someOperation() { System.out.println("This is from ConcreStateTwo"); mContext.changeStateCode(1); } }
|
public class Context { private State mState = null; private int stateCode = -1; public void changeStateCode(int stateCode) { this.stateCode = stateCode; } private void createState() { if(stateCode == -1 || stateCode == 1) { mState = new ConcreStateOne(this); }else if(stateCode == 2) { mState = new ConcreStateTwo(this); } } public void doSomeOperationInstate() { createState(); if(mState != null) { mState.someOperation(); } } }
|
public class Client { public static void main(String[] args) { Context mContext = new Context(); mContext.doSomeOperationInstate(); mContext.doSomeOperationInstate(); mContext.doSomeOperationInstate(); mContext.doSomeOperationInstate(); mContext.doSomeOperationInstate(); mContext.doSomeOperationInstate(); mContext.doSomeOperationInstate(); mContext.doSomeOperationInstate(); mContext.doSomeOperationInstate(); } }
|