状态(state)模式:状态模式的意图是,允许一个对象在其内部状改变时改变它的行为。看起来就像是改变了它的类一样。主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同的一系列类当中,可以把复杂的逻辑判断简单化。

状态模式的结构如下图:

JAVA 用状态模式实现状态机 java状态设计模式_JAVA 用状态模式实现状态机


从图中可以看出状态模式有以下角色:

1、抽象状态(State)角色:定义一个接口,用以封装环境对象的一个特定的状态所对应的行为。

2、具体状态(ConcreteState)角色:每一个具体状态类都实现了环境的一个状态所对的行为。

3、场景(Context)角色:定义客户端所感兴趣的接口,并且保留一个具体状态类的实例。这个具体状态类的实例给出此环境对象现有的状态。

上图用代码模拟如下:

抽象状态角色:

public interface State {
   public void change(Context context); 
}

场景角色类:

public class Context {

	private State state;

	public void change() {
		state.change(this);
	}

	public Context(State state) {
		super();
		this.state = state;
	}

	public State getState() {
		return state;
	}

	public void setState(State state) {
		this.state = state;
	}
}

具体状态角色:

public class ConcreteStateA implements State{

	@Override
	public void change(Context context) {
		// TODO Auto-generated method stub
		System.out.println("this is ConcreteStateA");   
        context.setState(new ConcreteStateB()); 
	}
	
}
public class ConcreteStateB implements State {

	@Override
	public void change(Context context) {
		// TODO Auto-generated method stub
		System.out.println("this is ConcreteStateB");   
        context.setState(new ConcreteStateA());
	}

}

测试类:

public class Client {

	public static void main(String[] args) {
		State state = new ConcreteStateA();
		Context context = new Context(state);
		// 初始状态是A
		context.change();
		// 装换一次后变成B
		context.change();
		// 再转换一次后又变成A
		context.change();
	}
}

运行结果:

this is ConcreteStateA
 this is ConcreteStateB
 this is ConcreteStateA

上面代码是两个状态切换,很符合家里灯的开关,A表示关,B表示开,按一下打开,再按一下关闭。

通过上面例子可以看出,状态模式将与特定状态相关的行为局部化,并且将不同状态的行为分割开来;所有状态相关的代码都存在于某个ConcereteState中,所以通过定义新的子类很容易地增加新的状态和转换;状态模式通过把各种状态转移逻辑分不到State的子类之间,来减少相互间的依赖。缺点是:会导致有很多State 的子类。 

状态模式和策略模式结构完全一样,很容易混淆,这里列举下状态模式和策略模式的区别:

1、状态模式有明显的状态过渡,从一个状态到另一个状态转换过程,在整个生命周期里有多个状态转换;而策略模式一旦环境角色选择了一个具体的策略类,那么在整个生命周期它始终不会改变;

2、状态模式多数是外在原因在环境角色中放入一个具体的状态类,而策略模式是自主选择一个具体的策略类;

3、状态模式选择一个状态是会明显告诉客户端的,而策略模式则不会告诉客户端选择了什么策略。