Vending Machine

Idea

The key point for this question is that you should recognize the states switching process. Essentially, it's a thinking about state pattern.

Four States for a vending machine:

  1. Empty (Nothing in vending machine) 无商品
  2. Coin Inserted 已投币
  3. No Coin Inserted 未投币
  4. Dispense a merchandise 出售商品

Four states switching

You can use integer to represent state like this:

      // 已投币   
      private final static int HAS_MONEY = 0;  
      // 未投币   
      private final static int NO_MONEY = 1;  
      // 售出商品   
      private final static int SOLD = 2;  
      // 商品售罄   
      private final static int SOLD_OUT = 3;

BUT it'd be better to use classes with designed inheritance relationship, like following

    // 已投币   
    State coninInsertedState = new CoinInsertedState(this);
    // 商品售罄  
    State emptyState = new EmptyState(this);
    // 未投币 
    State noCoinInsertedState = new NoCoinInsertedState(this);
    // 售出商品
    State dispensingState = new DispensingState(this);

Code

First We should think about state interface:

State.java

// State interface
import statepattern.exception.MachineWarning;
public interface State {

    public void insertCoin()throws MachineWarning;
    public void pressButton()throws MachineWarning;
    public void dispense()throws MachineWarning;
}

Concrete States implementations

ConinInsertedState.java

// Inserted Coin state
package statepattern;
import statepattern.exception.MachineWarning;
public class CoinInsertedState implements State{
    VendingMachine machine =null;
    public CoinInsertedState(VendingMachine machine) {
        this.machine =  machine;
    }
    public void insertCoin() throws MachineWarning{
        throw new MachineWarning("Coin is already inserted.");
    }
    public void dispense() throws MachineWarning{
        throw new MachineWarning("Dispense button is not pressed.");

    }
    public void pressButton() throws MachineWarning{
        machine.setMachineState(machine.getDispensingState());
    }
}

DispensingState.java

// Dispensing Merchandise
package statepattern;
import statepattern.exception.MachineWarning;
public class DispensingState implements State{
    VendingMachine machine ;
    DispensingState(VendingMachine machine) {
        this.machine = machine;
    }
    public void insertCoin() throws MachineWarning {
        throw new MachineWarning("wait ... previous order is processing");
    }
    public void pressButton() throws MachineWarning {
        throw new MachineWarning("wait ... previous order is processing");
    }
    public void dispense() throws MachineWarning {
        machine.setMachineState(machine.getNoCoinInsertedState());
    }
}

EmptyState.java

// Nothing in machine (Empty)
package statepattern;
import statepattern.exception.MachineWarning;
public class EmptyState implements State{
    VendingMachine machine;
    public EmptyState(VendingMachine machine) {
        this.machine =  machine;
    }
    public void insertCoin() throws MachineWarning{
        throw new MachineWarning("Can not process the request");
    }
    public void pressButton() throws MachineWarning{
        throw new MachineWarning("Invalid Action");
    }
    public void dispense() throws MachineWarning{
        throw new MachineWarning("Invalid Action");
    }
}

NoCoinInsertedState.java

// No coin inserted
package statepattern;
import statepattern.exception.MachineWarning;
public class NoCoinInsertedState implements State{
    VendingMachine machine;
    public NoCoinInsertedState(VendingMachine machine) {
        this.machine =  machine;
    }
    public void insertCoin() throws MachineWarning{
        if (!machine.isEmpty()) {
            machine.setMachineState(machine.getConinInsertedState());
        }
        else {
            throw new MachineWarning("Can not process request .. Machine is out of stock");
        }
    }
    public void pressButton() throws MachineWarning{
        throw new MachineWarning("No coin inserted ..");
    }
    public void dispense() throws MachineWarning{
        throw new MachineWarning("Invalid Operation");
    }
}

Then, we have to think about how to structure of vending machine object.

VendingMachine.java

package statepattern;
import statepattern.exception.MachineWarning;
public class VendingMachine {
    // declare 
    State coninInsertedState = new CoinInsertedState(this);
    State emptyState = new EmptyState(this);
    State noCoinInsertedState = new NoCoinInsertedState(this);
    State dispensingState = new DispensingState(this);


    State machineState = null;
    int capacity = 0;
    public VendingMachine() {
        machineState = noCoinInsertedState;
    }
    public void reFill(int count) {
        capacity += count;
        machineState = noCoinInsertedState;
    }
    /**
     * Two Actions performed by MAchine   
     */
    public void insertCoin() throws MachineWarning {
        machineState.insertCoin();
    }

    public void pressButton() throws MachineWarning {
        machineState.pressButton();
        machineState.dispense();
        capacity--;
    }

    public boolean isEmpty(){
        if(capacity<=0)
            return true;
        else
            return false;
    }

    public void setMachineState(State machineState) {
        this.machineState = machineState;
    }
    public State getMachineState() {
        return machineState;
    }
    public void setConinInsertedState(State coninInsertedState) {
        this.coninInsertedState = coninInsertedState;
    }
    public State getConinInsertedState() {
        return coninInsertedState;
    }
    public void setEmptyState(State emptyState) {
        this.emptyState = emptyState;
    }
    public State getEmptyState() {
        return emptyState;
    }
    public void setNoCoinInsertedState(State noCoinInsertedState) {
        this.noCoinInsertedState = noCoinInsertedState;
    }
    public State getNoCoinInsertedState() {
        return noCoinInsertedState;
    }
    public void setDispensingState(State dispensingState) {
        this.dispensingState = dispensingState;
    }
    public State getDispensingState() {
        return dispensingState;
    }
    public void setCapacity(int capacity) {
        this.capacity = capacity;
    }
    public int getCapacity() {
        return capacity;
    }
}

results matching ""

    No results matching ""