state模式
一、State模式定义:
允许一个对象在其状态改变时,改变它的行为。看起来对象似乎修改了它的类。
二、模式解说
State模式主要解决的是在开发中时常遇到的根据不同的状态需要进行不同的处理操作的问题,而这样的问题,大部分人是采用switch-case语句进行处理的,这样会造成一个问题:分支过多,而且如果加入一个新的状态就需要对原来的代码进行编译。State模式采用了对这些不同的状态进行封装的方式处理这类问题,当状态改变的时候进行处理然后再切换到另一种状态,也就是说把状态的切换责任交给了具体的状态类去负责.同时,State模式和 Strategy模式有很多相似的地方,需要说明的是两者的思想都是一致的,只不过封装的东西不同:State模式封装的是不同的状态,而Stategy 模式封装的是不同的算法。
三、结构图
State模式结构图如下:
四、怎么使用?
1)定义一个State接口,接口中有一个统一的方法,用以封装一个特定状态所对应的行为。
2)定义具体不同状态类ConcreteSate实现State接口。
3)每一个状态类都实现环境(Context)一个状态所对应的行为。
4)定义一个状态管理器Context.
五、一个例子
1: interface State{ 2: public void handle(Context ctx); 3: } 4: class ConcreteStateA implements State{ 5: 6: public void handle(Context ctx) { 7: System.out.println("handle by ConcreteStateA"); 8: if(ctx!=null){ 9: ctx.ChangeState(new ConcreteStateB()); 10: } 11: 12: } 13: } 14: class ConcreteStateB implements State{ 15: 16: public void handle(Context ctx) { 17: System.out.println("handle by ConcreteStateB"); 18: if(ctx!=null){ 19: ctx.ChangeState(new ConcreteStateA()); 20: } 21: 22: } 23: } 24: class Context{ 25: private State _state; 26: public Context(State state){ 27: _state=state; 28: } 29: public void request(){ 30: if(_state!=null){ 31: _state.handle(this); 32: } 33: } 34: public void ChangeState(State s){ 35: if(_state!=null){ 36: _state=null; 37: } 38: _state=s; 39: } 40: } 41: public class StateClient { 42: 43: public static void main(String[] args) { 44: State state=new ConcreteStateA(); 45: Context context=new Context(state); 46: context.request(); 47: context.request(); 48: context.request(); 49: context.request(); 50: 51: } 52: 53: }输出结果:
handle by ConcreteStateA
handle by ConcreteStateB
handle by ConcreteStateA
handle by ConcreteStateB
每请求一次,状态就更换一次,就执行对应的行为。
六、适用性
1)一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。
2)一个对象含有庞大的条件分支语句,这些分支依赖于它的状态。这个状态通常用一个或多个枚举常量表示。通常有多个操作包含这一相同的结构。State 模式将每一个分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。
七、优缺点
1)优点: 避免了为判断状态而产生的巨大的if或case语句。 将对象行为交给状态类维护后,对于上层程序而言,仅需要维护状态之间的转换规则。
2)会导致某些系统有过多的具体状态类。
八、参考
http://www.cppblog.com/converse/archive/2006/08/07/10902.html
http://www.blogjava.net/flying/archive/2006/08/29/66472.html