今天继续学习状态模式,通俗来讲,就是每个不同的状态会有不同的行为,拿现实生活来说,一个普通的上班族,7点的状态是刚刚起床,9点的状态是刚上班,精力充沛,12点的状态是吃饭。。。等等。在每一个不同的状态中,会有对应的事情要取做,那么这个状态模式怎么写呢?首先我第一想到的就是if-else。那我们一天有24小时,我们岂不是要写24个if-else么?那实在太恐怖了,而且一旦有变动,代价可是十分大的,所以,我们引进了状态模式,虽然代码量没有减少,甚至增多了,但是却符合设计原则中的单一职责和开-闭原则。
我们还是看一看代码,深入的了解一下,为了直观一些,我们不用上边的例子,我们拿电风扇来说,电风扇在不同的档位有不同的转速,这也是状态模式的一种体现。我们就拿这个来做例子,代码部分有注释,我就不过多解释了。
老样子,先看包结构
先来写一个通用的状态接口,每一个状态都要完成的工作
package com.state.state.intf;
import com.state.context.Context;
/**
* 状态接口,每一个状态都要实现的接口
* @author ZHENGWEI
* @date Jul 29, 2015
*/
public interface State {
/**
* 当前状态的下一个状态
*/
public void nextState(Context con);
/**
* 当前状态的上一个状态
*/
public void preState(Context con);
/**
* 获取当前状态
*/
public void getCurState();
}
之后是Context类,也叫上下文类
package com.state.context;
import com.state.state.intf.State;
/**
* 上下文类
* @author ZHENGWEI
* @date Jul 29, 2015
*/
public class Context {
private State state;
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
/**
* 当前状态的下一个状态
*/
public void next(){
this.state.nextState(this);
this.state.getCurState();
}
/**
* 当前状态的上一个状态
*/
public void pre(){
this.state.preState(this);
this.state.getCurState();
}
}
我们在调整状态时,不去使用State接口里的方法,而是通过上下文类,让它自己决定去调用具体哪个实例的方法
之后就是每一个具体的状态的类,有3个,分别是1档,2档,关闭档
package com.state.state.impl;
import com.state.context.Context;
import com.state.state.intf.State;
public class OneState implements State {
public void getCurState() {
System.out.println("当前是1档");
}
public void nextState(Context con) {
con.setState(new TwoState());
}
public void preState(Context con) {
con.setState(new OffState());
}
}
package com.state.state.impl;
import com.state.context.Context;
import com.state.state.intf.State;
public class TwoState implements State {
public void getCurState() {
System.out.println("当前是2档");
}
public void nextState(Context con) {
con.setState(new OffState());
}
public void preState(Context con) {
con.setState(new OneState());
}
}
package com.state.state.impl;
import com.state.context.Context;
import com.state.state.intf.State;
public class OffState implements State {
public void getCurState() {
System.out.println("当前档位是关闭");
}
public void nextState(Context con) {
con.setState(new OneState());
}
public void preState(Context con) {
con.setState(new TwoState());
}
}
在这里要注意,在实际应用中,这个具体的状态类应该是单例的,也就是说在一个JVM中,只存在这个类的一个实例对象,否则过多的状态转换会导致占用过多JVM资源。但是在这里我为了直观表达状态模式,就没有用单例,否则代码太乱的话会影响大家理解。
最后是测试类
package com.state.main;
import com.state.context.Context;
import com.state.state.impl.OneState;
import com.state.state.intf.State;
public class StateMain {
public static void main(String[] args) {
Context con = new Context();
State oneSta = new OneState();
con.setState(oneSta);
for(int i = 0; i < 10; i++){
con.next();
}
}
}
然后是结果
可以看到,如果我现在想加一个三档,只需要增加相关的类,别的地方只要微小的改动就可以了。