状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
示例—糖果机的实现
糖果机的主要流程是:开始没有硬币投入的状态,用户在投入硬币后,糖果机转为已投入硬币状态。这时,用户可以选择旋转把手或者退钱。选择旋转把手后,状态变更为已售出。糖果掉落后,如果还有糖果,状态变更为没有硬币;如果没有糖果了,状态变更为售光。选择退钱后,硬币退回,状态变更为没有硬币。还有一个抽奖机制,把手旋转的时候有10%的纪律掉落2个糖果。
UML图表示
状态模式-糖果机代码演示
状态接口
package State;
public interface State {
void insertQuarter();
void ejectQuarter();
void turnCrank();
void dispense();
}
无硬币状态类
package State;
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 inserted a quarter");
}
@Override
public void turnCrank() {
System.out.println("You need to pay first");
}
@Override
public void dispense() {
System.out.println("You need to pay first");
}
@Override
public String toString() {
return this.getClass().getName();
}
}
有硬币状态类
package State;
import java.util.Random;
public class HasQuarterState implements State {
GumballMachine gumballMachine;
Random randomWinner = new Random(System.currentTimeMillis());
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 toString() {
return this.getClass().getName();
}
}
售出状态类
package State;
public class SoldState implements State {
GumballMachine gumballMachine;
public SoldState(GumballMachine gumballMachine){
this.gumballMachine = gumballMachine;
}
@Override
public void insertQuarter() {
System.out.println("Please wait,we've 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 toString() {
return this.getClass().getName();
}
}
售罄状态类
package State;
public class SoldOutState implements State {
GumballMachine gumballMachine;
public SoldOutState(GumballMachine gumballMachine){
this.gumballMachine = gumballMachine;
}
@Override
public void insertQuarter() {
System.out.println("You can't insert a quarter,the machine is sold out");
}
@Override
public void ejectQuarter() {
System.out.println("You can't eject,you haven't inserted a quarter yet");
}
@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 toString() {
return this.getClass().getName();
}
}
获奖状态类
package State;
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 a quarter");
}
@Override
public void ejectQuarter() {
System.out.println("You can't eject");
}
@Override
public void turnCrank() {
System.out.println("Turning twice doesn't get you third gumball!");
}
@Override
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());
}
}
}
@Override
public String toString() {
return this.getClass().getName();
}
}
糖果机类
package State;
public class GumballMachine {
State soldOutState;
State noQuarterState;
State hasQuarterState;
State soldState;
State winnerState;
private State state = soldOutState;
private 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;
}
}
@Override
public String toString() {
return "GumballMachine has " + count + " gumballs now, current state is " + state.toString();
}
public void insertQuarter(){
state.insertQuarter();
}
public void ejectQuarter(){
state.ejectQuarter();
}
public void turnCrank(){
state.turnCrank();
state.dispense();
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public State getHasQuarterState(){
return hasQuarterState;
}
public State getNoQuarterState(){
return noQuarterState;
}
public State getSoldState(){
return soldState;
}
public State getSoldOutState(){
return soldOutState;
}
public State getWinnerState() {
return winnerState;
}
void releaseBall(){
System.out.println("A gumball comes rolling out the slot...");
if (count != 0){
count = count - 1;
}
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}
测试代码
package State;
public class GumballMachineTestDrive {
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);
}
}
测试结果
GumballMachine has 5 gumballs now, current state is State.NoQuarterState
You inserted a quarter
You turned...
YOU'RE A WINNER! You get two gumballs for your quarter
A gumball comes rolling out the slot...
A gumball comes rolling out the slot...
GumballMachine has 3 gumballs now, current state is State.NoQuarterState
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...
GumballMachine has 1 gumballs now, current state is State.NoQuarterState
网友评论