个人笔记,请勿被误导。
状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
这个模式把状态封装成独立的类,并将动作委托到代表当前状态的对象。
案例介绍:糖果机有五种状态:没有收到硬币、收到硬币、糖果售罄。几种状态之间转换的操作依次是:投币、摇杆、出糖果。出糖果后如果没有糖果就转到售罄状态,否则回到没有收到硬币的状态。这里面状态是易变的,所以要封装它。比如后来出一个新状态是中奖状态,中奖状态是收到硬币状态进行摇杆操作后有十分之一概率发生的。中奖会弹出两个糖果,相应转到售罄或没有收到硬币状态。所以把各个状态封装成类,它们继承自一个抽象类State,糖果机类(这里类名是Context)有State对象curState,标识当前状态。
要点:当状态转换是固定的时候,适合放在Context中,不固定时适合放在状态类中(这样有缺点:状态之间产生依赖)。状态类还可以被多个Context实例共享,要设置成静态。
与策略模式比较:两者比较像,都用了组合的方法。个人理解策略模式封装了算法族,客户可以改变算法对象从而改变行为;而状态模式里,客户有多种状态,不同状态对应不同行为,用户改变的状态,从而改变行为。
public abstract class State {
Context context;
public State(Context context){//抽象类有构造函数,子类就没有默认的构造函数了。
this.context = context;
}
public abstract void insertQuarter();
public abstract void ejectQuarter();
public abstract void turnCrank();
public abstract void dispense();
}
public class Context {
public State noQuarterState;
public State hasQuarterState;
public State winnerState;
public State soldOutState;
State curState = soldOutState;
public int count = 0;
public Context(int count){
this.count = count;
noQuarterState = new NoQuarterState(this);
hasQuarterState = new HasQuarterState(this);
winnerState = new WinnerState(this);
soldOutState = new SoldOutState(this);
}
public void insertQuarter() {
curState.insertQuarter();
}
public void ejectQuarter() {
curState.ejectQuarter();
}
public void turnCrank() {
curState.turnCrank();
}
public void dispense() {
curState.dispense();
}
public void setCurState(State state){
curState = state;
}
public boolean releaseBall(){
if (count > 0){
count--;
return true;
}
else curState = noQuarterState;
return false;
}
}
public class NoQuarterState extends State {
public NoQuarterState(Context context) {
super(context);
}
@Override
public void insertQuarter() {
context.setCurState(context.hasQuarterState);
}
@Override
public void ejectQuarter() {
}
@Override
public void turnCrank() {
}
@Override
public void dispense() {
}
}
public class HasQuarterState extends State {
public HasQuarterState(Context context) {
super(context);
}
@Override
public void insertQuarter() {
System.out.print("you has insert quarters");
}
@Override
public void ejectQuarter() {
}
@Override
public void turnCrank() {
double a = Math.random() * 10;
if ((int) a == 0)
context.setCurState(context.winnerState);
else context.releaseBall();
}
@Override
public void dispense() {
}
}
public class WinnerState extends State {
public WinnerState(Context context) {
super(context);
}
@Override
public void insertQuarter() {
}
@Override
public void ejectQuarter() {
}
@Override
public void turnCrank() {
}
@Override
public void dispense() {
if (context.releaseBall())
context.releaseBall();
}
}
public class SoldOutState extends State {
public SoldOutState(Context context) {
super(context);
}
@Override
public void insertQuarter() {
}
@Override
public void ejectQuarter() {
}
@Override
public void turnCrank() {
}
@Override
public void dispense() {
}
}
public void StatePattern(){
Context context = new Context(25);
context.insertQuarter();
context.ejectQuarter();
context.insertQuarter();
context.turnCrank();
context.dispense();
}