前几天由于忙工作上的事情,每天加班到10点左右才回家,回到家就没有再开电脑更新东西,今天早了一些回家,开始继续更新东西,今天要写的是状态模式,哦,对于一个没有状态的人来说,写状态模式,不知道会写成什么样子,反正是一起讨论用嘛,能把我所知道的清楚表达出来已经很心满意足啦。在理解状态模式的时候,我总觉得它和策略模式很像很像,有人说它们是孪生兄弟,那我们现在看看状态模式到底是一个什么样的东西。
状态模式是对象的一个行为模式,它允许一个对象在其内部状态改变的时候改变其行为,这个对象看上去就像改了了它的类一样。
下图是关于红绿灯转换的一个实现类图,具体的转换是这样子的,在初始的情况下,设定一个灯的状态,比如是绿灯,那么灯的下一个状态则是黄灯,紧接着是红灯,然后再是绿灯,依次循环;通过改变灯的状态,改变其行为。
下面是这个类图的实现代码:
package com.plabmedia.state;
public interface LightState {
/**
* 打印当前的状态
*/
public void print(Light light);}
package com.plabmedia.state;
public class RedLight implements LightState{
@Override
public void print(Light light) {
System.out.println("current state is red");
light.setState(new GreenLight());
}}
package com.plabmedia.state;
public class YellowLight implements LightState{
@Override
public void print(Light light) {
System.out.println("current state is yellow");
light.setState(new RedLight());
}}
package com.plabmedia.state;
public class GreenLight implements LightState {
@Override
public void print(Light light) {
System.out.println("current state is green");
light.setState(new YellowLight());
}}
package com.plabmedia.state;
public class Light {
private LightState state;
public LightState getState() {
return state;
}public void setState(LightState state) {
this.state = state;
}public void print(){
state.print(this);
}public Light(LightState state){
this.state = state;
}}
package com.plabmedia.state;
public class Client {
public static void main(String args[]){
Light light = new Light(new GreenLight());
light.print();
light.print();
light.print();
light.print();
light.print();
light.print();
}}
运行结果:
current state is green
current state is yellow
current state is red
current state is green
current state is yellow
current state is red
上面是对状态模式一个小小的实现,这个实现也仅仅是认识级的,在我们实际应用中,如果用到状态模式,应该比这个要负责的多,只是基本的结构是相似的。那我们下面针对状态模式做一些讨论。
1.在什么情况下使用状态模式:
- 一个对象的行为依赖于它所处的状态,对象的行为必须随着其状态的改变而改变;
- 需要多多重条件转移语句进行演化的时候,可以把每个分支封装成一个状态类;现在写代码的时候,我是不太喜欢用条件转移语句,特别是最好的那个else语句,我觉得它承担的东西太多了,前面不满足的情况它都要来处理,凭什么啊。
- 谁来定义状态的变化:客户端还是状态内部决定?这要看当时应用的环境,如果状态的变化是固定的,我觉得可以再客户端进行设定;如果状态的变化依赖于前一个状态,比如在工作流系统中,当前状态是依赖于前一个状态的,这需要状态内部来觉得。
- 状态对象创建时机:需要的时候创建?还是事先创建好所有的对象,供需要的时候调用?这要分系统需要来决定,如果一个系统,状态变化的顺序固定,不那么频繁,则可以在需要的时候创建所需要的对象;否则,对于频繁变化的状态,从性能上将,还是首先创建好各个状态对象,供需要时调用。
- 可以把环境类传到具体的状态类中,状态类在需要的时候调用环境类,比如示例中的样子,其实在每个状态类里面,也可以直接调用环境类的print方法,这样看来,Client只需要初始化环境类,然后就可以看到它的状态在不停地变化。