1. The scenario is resolved

1.1 Scenario Description

Candy vending machine, sold out 0, standby 1, coin 2, for candy 3.

1.2 OO design

  • Candy machine
public class CandyMachine { final static int SoldOutState = 0; final static int OnReadyState = 1; final static int HasCoin = 2; final static int SoldState = 3; private int state = SoldOutState; private int count = 0; public CandyMachine(int count) { this.count = count; if (count > 0) { state = OnReadyState; } } public void insertCoin() { switch (state) { case SoldOutState: System.out.println("you can't insert coin,the machine sold out!" ); break; case OnReadyState: state = HasCoin; System.out.println("you have inserted a coin,next,please turn crank!" ); break; case HasCoin: System.out.println("you can't insert another coin!" ); break; case SoldState: System.out.println("please wait! we are giving you a candy!" ); break; } } public void returnCoin() { switch (state) { case SoldOutState: System.out.println("you can't return,you haven't inserted a coin yet!" ); break; case OnReadyState: System.out.println("you haven't inserted a coin yet!" ); break; case HasCoin: System.out.println("coin return!" ); state = OnReadyState; break; case SoldState: System.out.println("sorry,you already have turned the crank!" ); break; } } public void turnCrank() { switch (state) { case SoldOutState: System.out.println("you turned,but there are no candies!" ); break; case OnReadyState: System.out.println("you turned,but you haven't inserted a coin!" ); break; case HasCoin: System.out.println("crank turn... !" ); state = SoldState; dispense(); break; case SoldState: System.out.println("we are giving you a candy,turning another get nothing,!" ); break; } } private void dispense() { count = count - 1; System.out.println("a candy rolling out!" ); if (count > 0) { state = OnReadyState; } else { System.out.println("Oo,out of candies"); state = SoldOutState; } } public void printstate() { switch (state) { case SoldOutState: System.out.println("***SoldOutState***"); break; case OnReadyState: System.out.println("***OnReadyState***"); break; case HasCoin: System.out.println("***HasCoin***"); break; case SoldState: System.out.println("***SoldState***"); break; }}}Copy the code
  • MainTest test class
public class MainTest { public static void main(String[] args) { CandyMachine mCandyMachine=new CandyMachine(1); mCandyMachine.printstate(); mCandyMachine.insertCoin(); mCandyMachine.printstate(); mCandyMachine.turnCrank(); mCandyMachine.printstate(); mCandyMachine.insertCoin(); mCandyMachine.printstate(); mCandyMachine.turnCrank(); mCandyMachine.printstate(); }}Copy the code

1.3 Demand Change

Added a game element: there is a 10% chance that you will get 2 candies, plus a “win” status.

1.4 Bringing Problems

After adding a state, the combination of states will increase a lot, and the previous logic will be modified if the modification, and more code will be modified.

2. Improve with design patterns

The state changes but the behavior does not, so you can encapsulate the state as an object, and the state encapsulates the action/behavior.

2.1 analysis

2.2 Redesign

2.3 the source code

  • interface State
Public interface State {// insertCoin public void insertCoin(); Public void returnCoin(); Public void turnCrank(); Public void dispense(); Public void printState (); }Copy the code
  • SoldOutState, HasCoin, OnReadyState, SoldState, WinnerState each State realizes the State interface
public class SoldOutState implements State { private CandyMachine mCandyMachine; public SoldOutState(CandyMachine mCandyMachine) { this.mCandyMachine=mCandyMachine; } @Override public void insertCoin() { System.out.println("you can't insert coin,the machine sold out!" ); } @Override public void returnCoin() { System.out.println("you can't return,you haven't inserted a coin yet!" ); } @Override public void turnCrank() { System.out.println("you turned,but there are no candies!" ); } @Override public void dispense() { } @Override public void printstate() { System.out.println("***SoldOutState***"); }}Copy the code
  • CandyMachine candy machine

public class CandyMachine {
	State mSoldOutState;
	State mOnReadyState;
	State mHasCoin;
	State mSoldState;
	State mWinnerState;
	private State state;
	private int count = 0;

	public CandyMachine(int count) {
		this.count = count;
		mSoldOutState = new SoldOutState(this);
		mOnReadyState = new OnReadyState(this);
		mHasCoin = new HasCoin(this);
		mSoldState = new SoldState(this);
		mWinnerState = new WinnerState(this);
		if (count > 0) {
			state = mOnReadyState;
		} else {
			state = mSoldOutState;
		}
	}

	public void setState(State state) {
		this.state = state;
	}

	public void insertCoin() {
		state.insertCoin();
	}

	public void returnCoin() {
		state.returnCoin();
	}

	public void turnCrank() {
		state.turnCrank();
		state.dispense();
	}

	void releaseCandy() {
		if (count > 0) {
			count = count - 1;
			System.out.println("a candy rolling out!");
		}
	}

	public int getCount() {
		return count;
	}

	public void printstate() {
		state.printstate();
	}
}
Copy the code
  • The test class
public class StateTest { public static void main(String[] args) { CandyMachine mCandyMachine = new CandyMachine(6); mCandyMachine.printstate(); mCandyMachine.insertCoin(); mCandyMachine.printstate(); mCandyMachine.turnCrank(); mCandyMachine.printstate(); mCandyMachine.insertCoin(); mCandyMachine.printstate(); mCandyMachine.turnCrank(); mCandyMachine.printstate(); }}Copy the code

3. Summary of design patterns

3.1 define

The state mode can change the behavior of an object based on changes in its internal state, as if modifying the class

3.2 Analysis

The state is variable, but the behavior is fixed. Therefore, the state is defined as the interface is variable, and some behaviors in the interface are fixed. Then, various specific states realize the state interface, and whether it is feasible to deal with various behaviors in each state object. State object to close modifications, to extend functionality.

4. Design pattern usage scenarios and attention

The meanings of policy mode, state mode, and template mode The policy mode can generally be used as the base of the state mode

5. Refer to the article

Total content in HeadFirst design mode and related videos