一、状态确立
万事万物都有状态,这个模式强调的就是对状态的把控,可以很轻松的在各个状态之间来回切换。
那我们先明确一下状态模式的定义:
允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。
简单理解就是在内部操控状态(调起了别的方法)但是外部对此感知好像是修改了它的类一般。
再拿类图来理解一下:
图中的三个角色:
Context:环境角色由它负责状态的切换;
State:抽象状态封装环境角色并实现状态的切换;
ConcreteState具体状态角色主要负责本状态要做的事,以及如何切换至其他状态。
二、具体实现
public class Context {
private IStates i;
//定义所有的状态
public final static OpenStates os = new OpenStates();
public final static CloseStates cs = new CloseStates();
public void setStatus(IStates i) {
this.i = i;
this.i.setContext(this);
}
public IStates getStuatus() {
return this.i;
}
public void open() {
this.i.openDoor();
}
public void close() {
this.i.closeDoor();
}
}
public abstract class IStates {
protected Context c;
public void setContext(Context c) {
this.c = c;
}
public abstract void openDoor();
public abstract void closeDoor();
}
public class CloseStates extends IStates{
@Override
public void openDoor() {
super.c.setStatus(Context.os);
super.c.getStuatus().openDoor();
}
@Override
public void closeDoor() {
System.out.println("电梯已关闭");
}
}
public class OpenStates extends IStates{
@Override
public void openDoor() {
System.out.println("电梯已开启");
}
@Override
public void closeDoor() {
super.c.setStatus(Context.cs);
super.c.getStuatus().closeDoor();
}
}
OK,再来看我刚才列出类的作用结合理解是不是会好一些?
三、总结
状态模式的优点不言而喻,他的缺点也异常明显,子类会根据状态的增多而膨胀。其实我一般解决方法就是通过数据库建立状态表。
那状态模式的使用场景也很明显了,当我们的行为要跟随状态的变化而变化的时候,这时候用状态模式再合适不过了。
还有就是分支语句太多的时候会导致我们的逻辑异常混乱。这时候也可以考虑引入状态模式。
值得一提的是,我们发现了状态的约束:
1.状态对象声明为静态常量,有几个状态对象就有几个静态常量
2.环境角色具有状态抽象角色定义的所有行为,具体执行时使用委托的方式
那最后,我们其实可以组合出更强更好的封装。那就是把已有的几种状态按一定顺序再来组装一下。哈哈没错了就是状态+建造喽。
OK,以上。不足之处欢迎指正。