定义:允许对象在内部状态改变时改变它的行为, 对象看起来好像修改了它的类;
形象比喻:跟MM交往时,一定要注意她的状态哦,在不同的状态时她的行为会有不同,比如你约她今天晚上去看电影,对你没兴趣的MM就会说 “有事情啦”,对你不讨厌但还没喜欢上的MM就会说“好啊,不过可以带上我同事么?”,已经喜欢上你的MM就会说“几点钟?看完电影再去泡吧怎么样?”,当然你看电影过程中表现良好的话,也可以把MM的状态从不讨厌不喜欢变成喜欢哦。
状态模式把所研究的对象的行为包装在不同的状态对象里,每一个状态对象都属于一个抽象状态类的一个子类。状态模式的意图是让一个对象在其内部状态改变的时候,其行为也随之改变。状态模式需要对每一个系统可能取得的状态创立一个状态类的子类。当系统的状态变化时,系统便改变所选的子类。
状态模式跟策略模式有相近的地方。 就状态模式而言, 我们将一群行为封装在状态对象中, context的行为随时可以委托到那些状态对象中的一个,我们把状态模式想成是不用在context中放置许多条件判断的替代方案。 就策略模式而言, 客户通常主动指定context所要组合的策略对象是哪一个。 我们把策略模式想成是除了继承之外的一种弹性替代方案。
本例中, 采用糖果机来模拟状态模式。糖果机四种基本状态:NoQuarter, HasQuarter, Sold, SoldOut。 在本例中我们还加入了另外一种状态:Winner,即随机出现中奖概率, 多出来一枚糖果。
下面是具体代码:
1、各种状态类定义:
State.java
interface State {
public void insertQuarter();
public void ejectQuarter();
public void turnCrank();
public void dispense();
}
NoQuarterState.java
public class NoQuarterState implements State {
GumballMachine gumballMachine;
public NoQuarterState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
@Override
public void insertQuarter() {
System.out.println("You inserted a quarter");
gumballMachine.setState(gumballMachine.getHasQuarterState());
}
@Override
public void ejectQuarter() {
System.out.println("You haven't insert a quarter");
}
@Override
public void turnCrank() {
System.out.println("You turned, but there's no quarter");
}
@Override
public void dispense() {
System.out.println("You need to pay first");
}
}
HasQuarterState.java
public class HasQuarterState implements State {
Random randWinner = new Random(System.currentTimeMillis());
GumballMachine gumballMachine;
public HasQuarterState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
@Override
public void insertQuarter() {
System.out.println("You can't insert another quarter");
}
@Override
public void ejectQuarter() {
System.out.println("Quarter returned");
gumballMachine.setState(gumballMachine.getNoQuarterState());
}
@Override
public void turnCrank() {
System.out.println("You turned...");
int winner = randWinner.nextInt(10);
if ((winner == 0) && (gumballMachine.getCount() > 1)) {
gumballMachine.setState(gumballMachine.getWinnerState());
}
gumballMachine.setState(gumballMachine.getSoldState());
}
@Override
public void dispense() {
System.out.println("No gumball dispensed");
}
}
SoldState.java
public class SoldState implements State {
GumballMachine gumballMachine;
public SoldState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
@Override
public void insertQuarter() {
System.out.println("Please wait, we're already giving you a gumball");
}
@Override
public void ejectQuarter() {
System.out.println("Sorry, you alredy turned the crank");
}
@Override
public void turnCrank() {
System.out.println("Turning twice doesn't get you another gumball");
}
@Override
public void dispense() {
gumballMachine.releaseBall();
if (gumballMachine.getCount() > 0) {
gumballMachine.setState(gumballMachine.getNoQuarterState());
}
else {
System.out.println("Oops, out of gumballs");
gumballMachine.setState(gumballMachine.getSoldOutState());
}
System.out.println("dispense the gumball");
}
}
SoldOutState.java
public class SoldOutState implements State {
GumballMachine gumballMachine;
public SoldOutState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
@Override
public void insertQuarter() {
System.out.println("Oops, out of gumballs, can't insert quarter");
}
@Override
public void ejectQuarter() {
System.out.println("Oops, out of gumballs, can't eject quarter");
}
@Override
public void turnCrank() {
System.out.println("Oops, out of gumballs, can't turn crank");
}
@Override
public void dispense() {
System.out.println("Oops, out of gumballs, can't dispense");
}
}
WinnerState.java
public class WinnerState implements State {
GumballMachine gumballMachine;
public WinnerState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
@Override
public void insertQuarter() {
System.out.println("Please wait, we're already giving you a gumball");
}
@Override
public void ejectQuarter() {
System.out.println("Sorry, you alredy turned the crank");
}
@Override
public void turnCrank() {
System.out.println("Turning twice doesn't get you another gumball");
}
@Override
public void dispense() {
gumballMachine.releaseBall();
if (gumballMachine.getCount() == 0) {
gumballMachine.setState(gumballMachine.getSoldOutState());
}
else {
gumballMachine.releaseBall();
if (gumballMachine.getCount() > 0) {
gumballMachine.setState(gumballMachine.getNoQuarterState());
}
else {
System.out.println("Oops, out of gumballs");
gumballMachine.setState(gumballMachine.getSoldOutState());
}
}
System.out.println("YOU'RE A WINNER! you get two gumballs for your quarter");
}
}
2、糖果机类
GumballMachine.java
public class GumballMachine {
State soldOutState;
State soldState;
State noQuarterState;
State hasQuarterState;
State winnerState;
State state = soldOutState;
int count = 0;
public GumballMachine(int numberGumballs) {
soldOutState = new SoldOutState(this);
soldState = new SoldState(this);
noQuarterState = new NoQuarterState(this);
hasQuarterState = new HasQuarterState(this);
winnerState = new WinnerState(this);
this.count = numberGumballs;
if (numberGumballs > 0) {
state = noQuarterState;
}
}
public void insertQuarter() {
state.insertQuarter();
}
public void ejectQuarter() {
state.ejectQuarter();
}
public void turnCrank() {
state.turnCrank();
state.dispense();
}
public int getCount() {
return count;
}
public State getSoldOutState() {
return soldOutState;
}
public State getSoldState() {
return soldState;
}
public State getNoQuarterState() {
return noQuarterState;
}
public State getHasQuarterState() {
return hasQuarterState;
}
public State getWinnerState() {
return winnerState;
}
void setState(State state) {
this.state = state;
}
void releaseBall() {
System.out.println("A gumball comes rolling out the slot...");
if (count != 0) {
count = count - 1;
}
}
//@Override
public String toString() {
return "Mighty Gumball, Inc.";//state.toString();
}
}
GumballMachineMain.java
public class GumballMachineMain {
public static void main(String[] args) {
GumballMachine gumballMachine = new GumballMachine(5);
System.out.println(gumballMachine);
gumballMachine.insertQuarter();
gumballMachine.turnCrank();
System.out.println(gumballMachine);
gumballMachine.insertQuarter();
gumballMachine.turnCrank();
gumballMachine.insertQuarter();
gumballMachine.turnCrank();
System.out.println(gumballMachine);
}
}
参考:《Head First设计模式》