传统的状态大都是这样的(状态模式)
public class GumballMachine { final static int SOLD_OUT = 0; final static int NO_QUARTER = 1; final static int HAS_QUARTER = 2; final static int SOLD = 3; }
然后嵌入大量的if - else
根究当前状态来进行某些操作,但是呢,现在我们是学过设计模式的人了,我们总是想搞出点幺蛾子来封装一下我们想要的东西,换句话说,我们要遵守"封装变化"原则
创建一个接口,填充我们需要的某些行为
/** * 状态接口 * @author Dougest 2017年7月16日 下午11:19:57 * */public interface State { void insertQuarter(); void ejectQuarter(); void turnCrank(); void dispense();}
然后通过几个实现类来实现我们不同状态写的具体细节
/** * 状态实现类 * @author Dougest 2017年7月16日 下午11:19:57 * */public class SoldState { void insertQuarter(); void ejectQuarter(); void turnCrank(); void dispense();}
/** * 状态实现类 * @author Dougest 2017年7月16日 下午11:19:57 * */public class SoldOutState { void insertQuarter(); void ejectQuarter(); void turnCrank(); void dispense();}
/** * 状态实现类 * @author Dougest 2017年7月16日 下午11:19:57 * */public class NoQuarterState { void insertQuarter(); void ejectQuarter(); void turnCrank(); void dispense();}
/** * 状态实现类 * @author Dougest 2017年7月16日 下午11:19:57 * */public class HasQuarterState { void insertQuarter(); void ejectQuarter(); void turnCrank(); void dispense();}
现在来具体实现
接口不变,实现新的调用类
/** * * @author Dougest 2017年7月17日 上午12:10:47 * */public class CompleMachine { State noQuarterState; State hasQuarterState; State soldOutState; State soldState; State state = soldOutState; int count = 0; public CompleMachine(int numberCompleMachine) { noQuarterState = new NoQuarterState(this); hasQuarterState = new HasQuarterState(this); soldOutState = new SoldOutState(this); soldState = new SoldState(this); this.count = numberCompleMachine; if(numberCompleMachine > 0) state = noQuarterState; } public void insertQuarter() { state.insertQuarter(); } public void ejectQuarter() { state.ejectQuarter(); } public void turnCrank() { state.turnCrank(); state.dispense(); } void setState(State state) { this.state = state; } void releaseBall() { if(count != 0) count = count -1; } public int getCount() { return this.count; } public State getNoQuarterState() { return noQuarterState; } public void setNoQuarterState(State noQuarterState) { this.noQuarterState = noQuarterState; } public State getHasQuarterState() { return hasQuarterState; } public void setHasQuarterState(State hasQuarterState) { this.hasQuarterState = hasQuarterState; } public State getSoldOutState() { return soldOutState; } public void setSoldOutState(State soldOutState) { this.soldOutState = soldOutState; } public State getSoldState() { return soldState; } public void setSoldState(State soldState) { this.soldState = soldState; } public State getState() { return state; } public void setCount(int count) { this.count = count; }
简单的实现某一个状态对象
/** * 状态实现类 * @author Dougest 2017年7月17日 上午12:11:16 * */public class HasQuarterState implements State { private CompleMachine compleMachine; public HasQuarterState(CompleMachine compleMachine) { this.compleMachine = compleMachine; } @Override public void insertQuarter() { System.out.println(""); } @Override public void ejectQuarter() { System.out.println(""); } @Override public void turnCrank() { System.out.println(""); } @Override public void dispense() { compleMachine.releaseBall(); if(compleMachine.getCount() > 0) compleMachine.setState(compleMachine.getHasQuarterState()); else compleMachine.setState(compleMachine.getSoldOutState()); }
现在我们已经做到了如下几点
1.将每个状态的行为局部化到他自己的类中
2.将容易的产生问题的if语句删除,方便日后维护
3.让每一个状态对修改关闭,对扩展开放,因为可以加入新的状态
4.创建了一个新的代码基和类,更能映射我们关于状态的业务逻辑,更容易阅读和理解
上面的代码我们实现了 定义状态模式
定义状态模式:允许对象在内部状态改变时改变他的行为,对象看起来好像修了他的类
这个就有点我们前面讲的命令模式的味道了, 定义状态模式将状态封装成对象,并将动作委托给代表当前状态的对象,我们知道行为会随着内部状态而改变
这里有一个习惯,如果没有共同的功能可以放在抽象类中,我们通常使用接口,就比如这个demo
要点:
状态模式允许一个对象基于内部的状态而拥有不同的行为
和程序状态机(PSM)不同,状态模式用类代表状态
context会将行为委托给当前状态对象
通过将每一个状态封装成对象,我们把以后需要做的任何改变局部化了
状态模式和策略模式有相同的类图,但是他们的意图不一样
策略模式通常会用行为或者算法来配置context类
状态模式允许context类随着状态的改变而改变行为
状态转换可以有State类或者context类控制
使用状态模式通常会使设计中出现大量的类
状态类可以被多个context共享