允许对象在内部状态改变时改变它的行为,对象看起来好像改变了它的类。
将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于具体状态类中,所以通过定义新的子类可以很容易地增加新的状态和转移。
使用状态模式可以消除庞大的条件分支语句。状态模式通过把各种状态转移逻辑分布到具体状态类中,来减少相互间的依赖。
类图

实现
1 2 3 4 5
| public abstract class State {
public abstract void handle(Context context);
}
|
1 2 3 4 5 6 7 8
| public class ConcreteStateA extends State {
@Override public void handle(Context context) { context.setState(new ConcreteStateB()); }
}
|
1 2 3 4 5 6 7 8
| public class ConcreteStateB extends State {
@Override public void handle(Context context) { context.setState(new ConcreteStateA()); }
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class Context {
private State state;
public Context(State state) { this.state = state; }
public State getState() { return state; }
public void setState(State state) { this.state = state; System.out.println("当前状态:" + state.getClass().getName()); }
public void request() { state.handle(this); } }
|
1 2 3 4 5 6 7 8 9 10
| public class Client {
public static void main(String[] args) { Context context = new Context(new ConcreteStateA()); context.request(); context.request(); context.request(); }
}
|
例:糖果销售机有四种状态,每种状态下销售机有不同的行为,状态可以发生转移,使得销售机的行为也发生改变。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public interface State {
public void insertQuarter();
public void ejectQuarter();
public void turnCrank();
public void dispense();
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
public class HasQuarterState implements State {
private GumballMachine gumballMachine;
public HasQuarterState(GumballMachine gumballMachine) { this.gumballMachine = gumballMachine; }
@Override public void insertQuarter() { System.out.println("已经投币,不用再投了..."); }
@Override public void ejectQuarter() { System.out.println("将币退还给您..."); gumballMachine.setState(gumballMachine.getNoQuarterState()); }
@Override public void turnCrank() { System.out.println("转动曲柄..."); gumballMachine.setState(gumballMachine.getSoldState()); }
@Override public void dispense() { System.out.println("请先转动曲柄..."); }
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
|
public class NoQuarterState implements State {
private GumballMachine gumballMachine;
public NoQuarterState(GumballMachine gumballMachine) { this.gumballMachine = gumballMachine; }
@Override public void insertQuarter() { System.out.println("投币成功..."); gumballMachine.setState(gumballMachine.getHasQuarterState()); }
@Override public void ejectQuarter() { System.out.println("没有投币,无法退还..."); }
@Override public void turnCrank() { System.out.println("请先投币,再转动曲柄..."); }
@Override public void dispense() { System.out.println("没有糖果发放..."); }
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
|
public class SoldOutState implements State {
private GumballMachine gumballMachine;
public SoldOutState(GumballMachine gumballMachine) { this.gumballMachine = gumballMachine; }
@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() { System.out.println("糖果售罄了,无法再发放糖果了..."); }
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
|
public class SoldState implements State {
private GumballMachine gumballMachine;
public SoldState(GumballMachine gumballMachine) { this.gumballMachine = gumballMachine; }
@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() { gumballMachine.releaseBall(); if (gumballMachine.getNumberGumballs() > 0) { gumballMachine.setState(gumballMachine.getNoQuarterState()); } else { gumballMachine.setState(gumballMachine.getSoldOutState()); } }
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
|
public class GumballMachine {
private State noQuarterState; private State hasQuarterState; private State soldState; private State soldOutState; private State state = soldOutState; private int numberGumballs;
public GumballMachine(int numberGumballs) { noQuarterState = new NoQuarterState(this); hasQuarterState = new HasQuarterState(this); soldState = new SoldState(this); soldOutState = new SoldOutState(this); this.numberGumballs = numberGumballs; if (numberGumballs > 0) { state = noQuarterState; } }
public void insertQuarter() { state.insertQuarter(); }
public void ejectQuarter() { state.ejectQuarter(); }
public void turnCrank() { state.turnCrank(); state.dispense(); }
public void releaseBall() { System.out.println("释放糖果..."); if (numberGumballs != 0) { numberGumballs -= 1; } }
public State getState() { return state; }
public void setState(State state) { this.state = state; }
public State getNoQuarterState() { return noQuarterState; }
public State getHasQuarterState() { return hasQuarterState; }
public State getSoldState() { return soldState; }
public State getSoldOutState() { return soldOutState; }
public int getNumberGumballs() { return numberGumballs; }
public void setNumberGumballs(int numberGumballs) { this.numberGumballs = numberGumballs; }
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| public class Client {
public static void main(String[] args) { GumballMachine gumballMachine = new GumballMachine(5);
gumballMachine.insertQuarter(); gumballMachine.turnCrank(); System.out.println("\n");
gumballMachine.insertQuarter(); gumballMachine.ejectQuarter(); gumballMachine.turnCrank(); System.out.println("\n");
gumballMachine.insertQuarter(); gumballMachine.turnCrank(); gumballMachine.insertQuarter(); gumballMachine.turnCrank(); gumballMachine.ejectQuarter(); System.out.println("\n");
gumballMachine.insertQuarter(); gumballMachine.insertQuarter(); gumballMachine.turnCrank(); gumballMachine.insertQuarter(); gumballMachine.turnCrank(); gumballMachine.insertQuarter(); gumballMachine.turnCrank(); }
}
|
输出结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| 投币成功... 转动曲柄... 释放糖果...
投币成功... 将币退还给您... 请先投币,再转动曲柄... 没有糖果发放...
投币成功... 转动曲柄... 释放糖果... 投币成功... 转动曲柄... 释放糖果... 没有投币,无法退还...
投币成功... 已经投币,不用再投了... 转动曲柄... 释放糖果... 投币成功... 转动曲柄... 释放糖果... 糖果售罄了,不要再投币了... 糖果售罄了,不要再转动曲柄了... 糖果售罄了,无法再发放糖果了...
|