- 什么是状态模式
- 状态模式的例子
- 状态模式的优缺点
- 状态模式的使用场景
- 闲言碎语
什么是状态模式
在现实生活我们在不同的时候点会做不同的事情.也会有不同的状态.当然,编程的是世界中我们也会在不同的时间可能有不同的状态,不同的处理,这时我们就要用到状态模式了.她的目的就是:允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。
UML:
状态模式的例子
状态模式的接口
package com.designPattern.state;
/**
* 状态模式的接口
*
* @author Jason
*
*/
public interface State {
// 每个状态需要完成任务的接口
public void doAction(Context time);
}
抽象层(可有可无)
package com.designPattern.state;
/**
* 状态的抽象实现
*
* @author jason
*
*/
public abstract class AbstractState implements State {
// 任务的默认实现
@Override
public void doAction(Context time) {
}
}
三个具体的状态(早上,中午,晚上)
package com.designPattern.state;
/**
* 早上的状态
*
* @author jason
*
*/
public class MorningState extends AbstractState {
public static int MIN_TIME = 0;
public static int MAX_TIME = 10;
@Override
public void doAction(Context time) {// 早上做的的事情
if (time.getTime() < MIN_TIME) {
System.out.println("请输入正确的时间!");
return;
}
if (MIN_TIME <= time.getTime() && MAX_TIME > time.getTime()) {
System.out.println("这是早上!");
} else {
time.setState(new AfternoonState());
time.doThing();
}
}
}
package com.designPattern.state;
/**
* 下午的状态
*
* @author jason
*
*/
public class AfternoonState extends AbstractState {
public static int MIN_TIME = 10;
public static int MAX_TIME = 14;
@Override // 下午应该做的事情
public void doAction(Context time) {
if (MIN_TIME > time.getTime()) {
time.setState(new MorningState());
time.doThing();
}
if (MIN_TIME <= time.getTime() && MAX_TIME > time.getTime()) {
System.out.println("这是中午!");
}
if (MAX_TIME < time.getTime()) {
time.setState(new EveningState());
time.doThing();
}
}
}
package com.designPattern.state;
/**
* 晚上的状态
*
* @author jason
*
*/
public class EveningState extends AbstractState {
public static int MIN_TIME = 14;
public static int MAX_TIME = 24;
@Override // 晚上做的事情
public void doAction(Context time) {
if (MIN_TIME > time.getTime()) {
time.setState(new AfternoonState());
time.doThing();
}
if (MIN_TIME <= time.getTime() && MAX_TIME > time.getTime()) {
System.out.println("这是晚上!");
}
if (time.getTime() > MAX_TIME) {
System.out.println("输入的时间有误");
}
}
}
端口类(对状态进行维护)
package com.designPattern.state;
/**
* 状态管理的容器
*
* @author jason
*
*/
public class Context {
public State state;
public int time;
public Context(int time) {
super();
this.state = new MorningState();// 默认为早上状态
this.time = time;
}
public void doThing() {
state.doAction(this);
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public int getTime() {
return time;
}
public void setTime(int time) {
this.time = time;
}
}
测试类
package com.designPattern.state;
import org.junit.Test;
/**
* 状态模式的测试类
*
* @author jason
*
*/
public class TestCase {
@Test
public void test() {
Context context = new Context(7);
context.doThing();
context.setTime(15);
context.doThing();
context.setTime(17);
context.doThing();
context.setTime(7);
context.doThing();
}
}
状态模式的优缺点
优点
在不同状态需要有不同响应的使用场景下,避免了使用if/else导致代码臃肿,使代码结构清晰的同时保证了拓展性和维护性。
缺点
增加了类的个数,让代码感觉有点混乱,但易于维护.
状态模式的使用场景
(1)对象的行为依赖于它的状态,并且可以在运行时根据状态改变行为。
(2)代码中包含大量与对象状态有关的if/else语句,这些条件对应于对象的各种状态,这些冗余条件语句的出现导致代码的可维护性和灵活性变差,这种情况适合使用状态模式进行优化。
闲言碎语
从代码可以看出,为了保证状态的转换,我们在具体的的状态类中也需要写大量的if-else去确保状态间进行正确的切换.我曾经尝试使用模板方法将其进行转换的的部分进行抽离.但发现无法进行完全抽离.存在这个问题的可能是我对状态模式的理解有误.也可能是与之结合的方法有误.这个问题待日后再试!
状态模式和策略模式从结构上看十分相似.但他们内部运行的机理是完全不同.可以拿策略模式的代码和状态模式进行比较便可知道!