介绍
如题所示,今天要介绍的是一种争对状态转化的一种设计,这种设计应用也比较常见,风扇的几档是一个状态转换,空调的模式也是状态转换,当然怎么设计这种转换也有很多实现方式,今天介绍的是一种通用的,个人觉得好用的设计模式。
实现
我们采用委托给一个Context类来实现状态转化的功能,在这种方案里,每一个状态就是一个类,状态转化说白了就是变成新类,为了帮助大家理解,这里通过举一个例子来说明。
这里有一个任务,有3种状态,等待,进行,结束,只能依次转化。
Context管理器
首先我们需要一个Context,我们所有的对State的操作都在这里进行,让我们分析下这个Context里应该有些什么操作:
1.应该有个属性储存State
2.初始化状态为waiting
3.要转化状态,就需要一个方法来把State变成一个新的状态类(这里后面State使用)
4.可以进行状态转化,也就是进行下一步
5.可以返回当前的状态
差不多了,我们实现一下:
public class Context {
private State state; //第一点
public Context() {
state = new waiting();//第二点,在构造时初始化为waiting
}
/**
* 设置状态,对应第三点,在State中调用了这个东西
* @param 状态
*/
public void setState(State state) {
this.state = state;
}
/**
* 第四点,变成下一个状态,交给state来做
* 这里如果不能进行下一步也就是ended,抛出异常,让外面处理
*/
public void next() throws Exception {
state.next(this);//把这个管理器作为参数传进去
}
/**
*第五点
* @return 状态
*/
public State getState() {
return state;
}
State接口
我们前面说了,接口是一个蓝图,我们要设计好所有State应有的功能:
1.进行下一步
2.进行字符串化,表明自己的状态
实现:
public interface State {
/**
* 下一个状态,当然这里有可能会出错,比如ended
*/
public void next(Context c) throws Exception;
/**
* @return 状态字符串
*/
public String toString();
}
State实现
这里具体实现即可,注意这里的next调用Context的setState方法来完成状态类的改变,然后因为ended不能进行下一步,所以直接抛出异常,让外面处理好了。因为waiting和running基本一样,下面给出waiting和ended的实现:
public class waiting implements State{
@Override
public void next(Context c) throws Exception{
c.setState(new running());//调用管理器的setState变成下一步的状态
}
@Override
public String toString() {
return "waiting";
}
}
public class ended implements State{
@Override
public void next(Context c) throws Exception{
throws new Exception("ended can not use next");//不能进行下一步,直接抛出错误
}
@Override
public String toString() {
return "toString";
}
}
上面3部分合起来,就可以用于模拟State,使用时只需委托给Context即可。