状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。

类图

(图片源于网络)

代码实现(Java)

// State.javapublic interface State {                                                                           public void insertQuarter();    public void ejectQuarter();    public void turnCrank();    public void dispense();}

// SoldState.javapublic class SoldState implements State {    GumballMachine gumballMachine;                                                      public SoldState(GumballMachine gumballMachine) {        this.gumballMachine = gumballMachine;    }                                                            public void insertQuarter() {        System.out.println("Please wait, we're already giving you a gumball");    }                                                      public void ejectQuarter() {        System.out.println("Sorry, you already turned the crank");    }                                                      public void turnCrank() {        System.out.println("Turning twice doesn't get you another gumball!");    }                                                      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());        }    }                                                      public String toString() {        return "dispensing a gumball";    }}

// SoldOutState.javapublic class SoldOutState implements State {    GumballMachine gumballMachine;                                                   public SoldOutState(GumballMachine gumballMachine) {        this.gumballMachine = gumballMachine;    }                                                   public void insertQuarter() {        System.out.println("You can't insert a quarter, the machine is sold out");    }                                                   public void ejectQuarter() {        System.out.println("You can't eject, you haven't inserted a quarter yet");    }                                                   public void turnCrank() {        System.out.println("You turned, but there are no gumballs");    }                                                   public void dispense() {        System.out.println("No gumball dispensed");    }                                                   public String toString() {        return "sold out";    }}

// NoQuarterState.javapublic class NoQuarterState implements State {    GumballMachine gumballMachine;                                                public NoQuarterState(GumballMachine gumballMachine) {        this.gumballMachine = gumballMachine;    }                                                public void insertQuarter() {        System.out.println("You inserted a quarter");        gumballMachine.setState(gumballMachine.getHasQuarterState());    }                                                public void ejectQuarter() {        System.out.println("You haven't inserted a quarter");    }                                                public void turnCrank() {        System.out.println("You turned, but there's no quarter");     }                                                public void dispense() {        System.out.println("You need to pay first");    }                                                public String toString() {        return "waiting for quarter";    }}

// HasQuarterState.javapublic class HasQuarterState implements State {    Random randomWinner = new Random(System.currentTimeMillis());    GumballMachine gumballMachine;                                        public HasQuarterState(GumballMachine gumballMachine) {        this.gumballMachine = gumballMachine;    }                                         public void insertQuarter() {        System.out.println("You can't insert another quarter");    }                                        public void ejectQuarter() {        System.out.println("Quarter returned");        gumballMachine.setState(gumballMachine.getNoQuarterState());    }                                        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());        }    }    public void dispense() {        System.out.println("No gumball dispensed");    }                                        public String toString() {        return "waiting for turn of crank";    }}

// WinnerState.javapublic class WinnerState implements State {    GumballMachine gumballMachine;                              public WinnerState(GumballMachine gumballMachine) {        this.gumballMachine = gumballMachine;    }                              public void insertQuarter() {        System.out.println("Please wait, we're already giving you a Gumball");    }                              public void ejectQuarter() {        System.out.println("Please wait, we're already giving you a Gumball");    }                              public void turnCrank() {        System.out.println("Turning again doesn't get you another gumball!");    }                              public void dispense() {        System.out.println("YOU'RE A WINNER! You get two gumballs 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());            }        }    }                              public String toString() {        return "despensing two gumballs for your quarter, because YOU'RE A WINNER!";    }}

// GumballMachine.javapublic class GumballMachine {                 State soldOutState;    State noQuarterState;    State hasQuarterState;    State soldState;    State winnerState;                 State state = soldOutState;    int count = 0;                 public GumballMachine(int numberGumballs) {        soldOutState = new SoldOutState(this);        noQuarterState = new NoQuarterState(this);        hasQuarterState = new HasQuarterState(this);        soldState = new SoldState(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;        }    }                 int getCount() {        return count;    }                 void refill(int count) {        this.count = count;        state = noQuarterState;    }    public State getState() {        return state;    }    public State getSoldOutState() {        return soldOutState;    }    public State getNoQuarterState() {        return noQuarterState;    }    public State getHasQuarterState() {        return hasQuarterState;    }    public State getSoldState() {        return soldState;    }    public State getWinnerState() {        return winnerState;    }                 public String toString() {        StringBuffer result = new StringBuffer();        result.append("\nMighty Gumball, Inc.");        result.append("\nJava-enabled Standing Gumball Model #2004");        result.append("\nInventory: " + count + " gumball");        if (count != 1) {            result.append("s");        }        result.append("\n");        result.append("Machine is " + state + "\n");        return result.toString();    }}

测试代码

//GumballMachineTestDrive.javapublic class GumballMachineTestDrive {    public static void main(String[] args) {        GumballMachine gumballMachine =            new GumballMachine(10);        System.out.println(gumballMachine);        gumballMachine.insertQuarter();        gumballMachine.turnCrank();        gumballMachine.insertQuarter();        gumballMachine.turnCrank();        System.out.println(gumballMachine);        gumballMachine.insertQuarter();        gumballMachine.turnCrank();        gumballMachine.insertQuarter();        gumballMachine.turnCrank();        System.out.println(gumballMachine);        gumballMachine.insertQuarter();        gumballMachine.turnCrank();        gumballMachine.insertQuarter();        gumballMachine.turnCrank();        System.out.println(gumballMachine);        gumballMachine.insertQuarter();        gumballMachine.turnCrank();        gumballMachine.insertQuarter();        gumballMachine.turnCrank();        System.out.println(gumballMachine);        gumballMachine.insertQuarter();        gumballMachine.turnCrank();        gumballMachine.insertQuarter();        gumballMachine.turnCrank();        System.out.println(gumballMachine);    }}

运行效果

Mighty Gumball, Inc.

Java-enabled Standing Gumball Model #2004

Inventory: 10 gumballs

Machine is waiting for quarter

You inserted a quarter

You turned...

A gumball comes rolling out the slot...

You inserted a quarter

You turned...

A gumball comes rolling out the slot...

Mighty Gumball, Inc.

Java-enabled Standing Gumball Model #2004

Inventory: 8 gumballs

Machine is waiting for quarter

You inserted a quarter

You turned...

A gumball comes rolling out the slot...

You inserted a quarter

You turned...

A gumball comes rolling out the slot...

Mighty Gumball, Inc.

Java-enabled Standing Gumball Model #2004

Inventory: 6 gumballs

Machine is waiting for quarter

You inserted a quarter

You turned...

A gumball comes rolling out the slot...

You inserted a quarter

You turned...

A gumball comes rolling out the slot...

Mighty Gumball, Inc.

Java-enabled Standing Gumball Model #2004

Inventory: 4 gumballs

Machine is waiting for quarter

You inserted a quarter

You turned...

A gumball comes rolling out the slot...

You inserted a quarter

You turned...

A gumball comes rolling out the slot...

Mighty Gumball, Inc.

Java-enabled Standing Gumball Model #2004

Inventory: 2 gumballs

Machine is waiting for quarter

You inserted a quarter

You turned...

A gumball comes rolling out the slot...

You inserted a quarter

You turned...

A gumball comes rolling out the slot...

Oops, out of gumballs!

Mighty Gumball, Inc.

Java-enabled Standing Gumball Model #2004

Inventory: 0 gumballs

Machine is sold out