状态模式
定义:
允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
例子:
1、状态接口,任何状态都实现这个相同的接口,这样一来,状态之间可以互相替换。
public interface State {
void insertQuarter();
void ejectQuarter();
void turnCrank();
void dispense();
String getStateName();
}
2、具体状态,每个具体状态都提供了自己对于请求的实现,所以当context(之后的糖果机)改变状态时行为也跟着改变。
-无投币状态
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 havn't inserted 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 pay first");
}
@Override
public String getStateName() {
return "NoQuarterState";
}
}
- 已投币状态
public class HasQuarterState implements State {
Random randomWinner = 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 = randomWinner.nextInt(10);
if ((winner == 0) && (gumballMachine.getCount() > 1)) {
gumballMachine.setState(gumballMachine.getWinnerState());
} else {
gumballMachine.setState(gumballMachine.getSoldState());
}
}
@Override
public void dispense() {
/** 此状态不恰当动作 */
System.out.println("No gumball dispensed");
}
@Override
public String getStateName() {
return "HasQuarterState";
}
}
售出状态
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 already 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());
}
}
@Override
public String getStateName() {
return "SoldState";
}
}
售空状态
public class SoldOutState implements State {
GumballMachine gumballMachine;
public SoldOutState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
@Override
public void insertQuarter() {
System.out.println("Sorry , no gumball ! You can't inserted a quarter");
}
@Override
public void ejectQuarter() {
System.out.println("You can't enject.");
}
@Override
public void turnCrank() {
System.out.println("You turned, but there are no gumballs");
}
@Override
public void dispense() {
System.out.println("No gumball dispensed");
}
@Override
public String getStateName() {
return "SoldOutState";
}
}
winner状态(百分之10的机会一下掉2颗 ):
public class WinnerState implements State {
GumballMachine gumballMachine;
public WinnerState(GumballMachine gumballMachine){
this.gumballMachine = gumballMachine;
}
@Override
public void insertQuarter() {
System.out.println("You can't insert anthor quarter");
}
@Override
public void ejectQuarter() {
System.out.println("Can't eject, you have turned crank");
}
@Override
public void turnCrank() {
System.out.println("Needn't turn crank again!");
}
@Override
public void dispense() {
System.out.println("YOU'RE A WINNER! you get two gumblls for your quarter");
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());
}
}
}
@Override
public String getStateName() {
return "winner state";
}
}
糖果机,即Context(上下文)
public class GumballMachine {
State noQuarterState;
State hasQuarterState;
State soldState;
State soldOutState;
State winnerState;
State state = soldOutState;
int count = 0;
public GumballMachine(int numberGumballs){
noQuarterState = new NoQuarterState(this);
hasQuarterState = new HasQuarterState(this);
soldState = new SoldState(this);
soldOutState = new SoldOutState(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();
}
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;
}
}
public State getNoQuarterState() {
return noQuarterState;
}
public State getHasQuarterState() {
return hasQuarterState;
}
public State getSoldState() {
return soldState;
}
public State getSoldOutState() {
return soldOutState;
}
public State getWinnerState(){
return winnerState;
}
public int getCount(){
return count;
}
public String toString(){
System.out.println(" --- Gumball Machine ---");
System.out.println("gumball numbers : " + count);
System.out.println("machine states : " + state.getStateName());
return null;
}
}
测试类:
public class MyGumballMachine {
public static void main(String[] args){
GumballMachine gumballMachine = new GumballMachine(5);
gumballMachine.toString();
gumballMachine.insertQuarter();
gumballMachine.turnCrank();
gumballMachine.toString();
gumballMachine.insertQuarter();
gumballMachine.turnCrank();
gumballMachine.insertQuarter();
gumballMachine.turnCrank();
gumballMachine.insertQuarter();
gumballMachine.turnCrank();
gumballMachine.toString();
}
}
结果:
--- Gumball Machine ---
gumball numbers : 5
machine states : NoQuarterState
You inserted a quarter
You turned ...
A gumball comes rolling out the slot ...
--- Gumball Machine ---
gumball numbers : 4
machine states : NoQuarterState
You inserted a quarter
You turned ...
A gumball comes rolling out the slot ...
You inserted a quarter
You turned ...
YOU'RE A WINNER! you get two gumblls for your quarter
A gumball comes rolling out the slot ...
A gumball comes rolling out the slot ...
You inserted a quarter
You turned ...
A gumball comes rolling out the slot ...
Oops, out of gumballs!
--- Gumball Machine ---
gumball numbers : 0
machine states : SoldOutState
结果:
- 状态模式允许一个对象基于内部状态而拥有不同的行为。
- 和程序状态机(PSM)不同,状态模式用类代表状态。
- Context会将行为委托给当前对象。
- 通过将每个状态封装进一个类,我们把以后需要做的任何改变局部化了!
- 状态模式和策略模式有相同的类图,但是它们的意图不同。
- 策略模式通常会用行为或算法来配置Context类。
- 状态模式允许Context随着状态的改变而改变行为。
- 状态改变可以由State类或Context类控制。
- 使用状态模式通常会导致设计中类的数目大量增加。
- 状态类可以被多个Context实例共享。