JAVA设计模式学习23——状态模式
程序员文章站
2022-03-02 12:17:30
...
状态(state)模式:状态模式的意图是,允许一个对象在其内部状改变时改变它的行为。看起来就像是改变了它的类一样。主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同的一系列类当中,可以把复杂的逻辑判断简单化。
状态模式的结构如下图:
从图中可以看出状态模式有以下角色:
1、抽象状态(State)角色:定义一个接口,用以封装环境对象的一个特定的状态所对应的行为。
2、具体状态(ConcreteState)角色:每一个具体状态类都实现了环境的一个状态所对的行为。
3、场景(Context)角色:定义客户端所感兴趣的接口,并且保留一个具体状态类的实例。这个具体状态类的实例给出此环境对象现有的状态。
上图用代码模拟如下:
package state; /** * *作者:alaric *时间:2013-9-3下午10:12:05 *描述:抽象状态类 */ public interface State { public void change(Context context); }
package state; /** * *作者:alaric *时间:2013-9-3下午10:12:27 *描述:实现状态类 */ public class ConcreteStateA implements State { @Override public void change(Context context) { System.out.println("this is ConcreteStateA"); context.setState(new ConcreteStateB()); } }
package state; /** * *作者:alaric *时间:2013-9-3下午10:13:02 *描述:实现状态类 */ public class ConcreteStateB implements State { @Override public void change(Context context) { System.out.println("this is ConcreteStateB"); context.setState(new ConcreteStateA()); } }
package state; /** * *作者:alaric *时间:2013-9-3下午10:13:20 *描述:环境角色类 */ 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; } }
package state; /** * *作者:alaric *时间:2013-9-3下午10:13:37 *描述:测试类 */ public class Client { /** *作者:alaric *时间:2013-9-3下午7:52:05 *描述: */ 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表示开,按一下打开,再按一下关闭。下面举个例子,马路上的红绿灯大家都知道的,它有三个状态控制三个不同颜色的灯,我们分别用RedState(红灯状态),GreenState(绿灯状态),YellowState(黄灯状态)表示三个灯的状态,用Light表示灯来模拟,类图如下:
模拟代码如下:
package state.example; /** * *作者:alaric *时间:2013-9-7上午11:14:32 *描述:抽象状态类 */ public interface State { public void change(Light light); }
package state.example; public class GreenState implements State { private static final Long SLEEP_TIME = 2000L; @Override public void change(Light light) { System.out.println("现在是绿灯,可以通行"); //绿灯亮1秒 try { Thread.sleep(SLEEP_TIME); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } light.setState(new YellowState()); } }
package state.example; public class YellowState implements State { private static final Long SLEEP_TIME = 500L; @Override public void change(Light light) { System.out.println("现在是黄灯,警示"); //红灯亮0.5秒 try { Thread.sleep(SLEEP_TIME); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } light.setState(new RedState()); } }
package state.example; public class RedState implements State { private static final Long SLEEP_TIME = 1000L; @Override public void change(Light light) { System.out.println("现在是红灯,禁止通行"); //红灯亮1秒 try { Thread.sleep(SLEEP_TIME); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } light.setState(new GreenState()); } }
package state.example; public class Light { private State state; private void change(){ state.change(this); } public void work(){ while(true){ change(); } } public Light(State state) { super(); this.state = state; } public State getState() { return state; } public void setState(State state) { this.state = state; } }
package state.example; /** * *作者:alaric *时间:2013-9-7上午11:27:41 *描述:测试客户端 */ public class Client { /** *作者:alaric *时间:2013-9-7上午11:27:34 *描述: */ public static void main(String[] args) { //假设路灯开始是绿灯 State state = new GreenState(); Light light = new Light(state); light.work(); } }运行结果:
现在是绿灯,可以通行
现在是黄灯,警示
现在是红灯,禁止通行
现在是绿灯,可以通行
现在是黄灯,警示
现在是红灯,禁止通行
现在是绿灯,可以通行
现在是黄灯,警示
.....
通过上面例子可以看出,状态模式将与特定状态相关的行为局部化,并且将不同状态的行为分割开来;所有状态相关的代码都存在于某个ConcereteState中,所以通过定义新的子类很容易地增加新的状态和转换;状态模式通过把各种状态转移逻辑分不到State的子类之间,来减少相互间的依赖。缺点是:会导致有很多State 的子类。
状态模式和策略模式结构完全一样,很容易混淆,这里列举下状态模式和策略模式的区别:
1、状态模式有明显的状态过渡,从一个状态到另一个状态转换过程,在整个生命周期里有多个状态转换;而策略模式一旦环境角色选择了一个具体的策略类,那么在整个生命周期它始终不会改变;
2、状态模式多数是外在原因在环境角色中放入一个具体的状态类,而策略模式是自主选择一个具体的策略类;
3、状态模式选择一个状态是会明显告诉客户端的,而策略模式则不会告诉客户端选择了什么策略。
设计模式系列目录: