// -------- State Interface --------
interface State {
void insertCoin();
void turnCrank();
}
// -------- No Coin State --------
class NoCoinState implements State {
GumballMachine machine;
NoCoinState(GumballMachine m) { this.machine = m; }
public void insertCoin() {
System.
out.
println("Coin inserted."); machine.setState(machine.hasCoinState);
}
public void turnCrank() {
System.
out.
println("Insert coin first."); }
}
// -------- Has Coin State --------
class HasCoinState implements State {
GumballMachine machine;
HasCoinState(GumballMachine m) { this.machine = m; }
public void insertCoin() {
System.
out.
println("Coin already inserted."); }
public void turnCrank() {
System.
out.
println("Crank turned. Dispensing..."); machine.releaseBall();
if (machine.count > 0)
machine.setState(machine.noCoinState);
else
machine.setState(machine.soldOutState);
}
}
// -------- Sold Out State --------
class SoldOutState implements State {
GumballMachine machine;
SoldOutState(GumballMachine m) { this.machine = m; }
public void insertCoin() {
System.
out.
println("Machine is sold out."); }
public void turnCrank() {
System.
out.
println("Nothing happens, sold out."); }
}
// -------- Gumball Machine --------
class GumballMachine {
State noCoinState;
State hasCoinState;
State soldOutState;
State state;
int count = 0;
public GumballMachine(int gumballs) {
noCoinState = new NoCoinState(this);
hasCoinState = new HasCoinState(this);
soldOutState = new SoldOutState(this);
count = gumballs;
state = (count > 0) ? noCoinState : soldOutState;
}
void setState(State s) { state = s; }
void releaseBall() {
System.
out.
println("A gumball comes out..."); if (count > 0) count--;
}
// Public API
void insertCoin() { state.insertCoin(); }
void turnCrank() { state.turnCrank(); }
}
// -------- Test --------
public class Main {
public static void main
(String[] args
) { GumballMachine gm = new GumballMachine(2);
gm.insertCoin();
gm.turnCrank();
gm.insertCoin();
gm.turnCrank();
gm.insertCoin(); // Should say sold out
gm.turnCrank();
}
}