- IState declares InsertQuarter, EjectQuarter, TurnCrank, and Dispense.
- SoldState, SoldOutState, NoQuarterState, and HasQuarterState implement that contract and retain the GumballMachine reference.
9.3 State Pattern Lab
This assignment is based on Head First Design Patterns: p. 385-423
Work through the stories in order. Use the acceptance criteria to check each feature, and complete the nested tasks using the specified names, values, and scenarios.
9.3 State LastName.zip
9.3 State LastName.zipCurrently the GumballMachine class has methods with very large conditional statements that control what happens. If we were to add another "state" to the gumball machine we would have to add logic to every single method. For every state we have the code gets larger and less manageable.
<<interface>> IState InsertQuarter() EjectQuarter() TurnCrank() Dispense() Four following class will implement IState SoldState - gumballMachine: GumballMachine + SoldState (gumballMachine: GumballMachine) + InsertQuarter() + EjectQuarter() + TurnCrank() + Dispense() SoldOutState - gumballMachine: GumballMachine + SoldOutState (gumballMachine: Gumball Machine) + InsertQuarter() + EjectQuarter() + TurnCrank() + Dispense() NoQuarterState - gumball Machine: GumballMachine + NoQuarter State(gumballMachine: GumballMachine) + InsertQuarter() + EjectQuarter() + TurnCrank() + Dispense() - gumballMachine: Gumball Machine + HasQuarter State (gumballMachine: GumballMachine) + InsertQuarter() + EjectQuarter() + TurnCrank() + Dispense()
GumballMachine
Remove the following fields
- HAS_QUARTERthe following fields
- HAS_QUARTER: : int <readonly>
- NO_QUARTER: : int <readonly>
- SOLD: : int <readonly>
- SOLD_OUT. int <readonly>
- state: : int
Add the following fields
- soldOutStatethe following fields
- soldOutState: : IState
- noQuarterState: : IState
- hasQuarter State: IState
- soldState: : IState
- currentState: : IState
Add the following properties
+ SoldOutStatethe following properties
+ SoldOutState: : IState <get>
+ NoQuarterState: : IState <get
+ HasQuarter State: IState <get>
+ SoldState: : IState <get>
+ CurrentState: : IState <get> <set>Each "state" class needs to have a reference to the GumballMachine object to modify it.
For this step we are going to be breaking apart all of those huge if/else statements and putting them in their proper "state" class. The easiest way to accomplish this is to put the classes into split view.
Cut the line of code from the InsertQuarter method in the GumballMachine class in the HAS_QUARTER condition and paste it into the InsertQuarter method in the HasQuarterState class.

Cut the line of code from the Dispense method in the GumballMachine class in the HAS_QUARTER condition and paste it into the Dispense method in the HasQuarterState class.
Cut the lines of code from the EjectQuarter method in the GumballMachine class in the HAS_QUARTER condition and paste them into the EjectQuarter method in the HasQuarterState class.
In the EjectQuarter method in the HasQuarterState class, instead of the line that assigns state, assign the gumballMachine object's CurrentState property to the gumballMachine object's NoQuarterState property.

Cut the lines of code from the TurnCrank method in the GumballMachine class in the HAS_QUARTER condition and paste them into the TurnCrank method in the HasQuarterState class.
In the TurnCrank method in the HasQuarterState class, instead of the line that assigns state*, assign the gumballMachine object's CurrentState property to the gumballMachine object's SoldState property. Remove the call to Dispense.
Calling Dispense here wouldn't make much sense since in this "state" class the Dispense method prints out "No gumball dispensed".
The InsertQuarter method should be the only method that changes the state of the gumball machine.
None of the methods should change the state of the gumball machine.
In the GumballMachine class, add a method named ReleaseBall that reduces the count by 1 and write out "A gumball comes rolling out of the slot".
Add a Count getter to the GumballMachine class.
The Dispense method is the only method that should change the state of the gumball machine.



Mighty Gumball, Inc.
Inventory.
Inventory: : 5
Machine is waiting for quarter...
.
You inserted a quarter
You turned...
.
A gumball comes rolling out out of the slot.
Mighty Gumball, Inc.
Inventory: : 4
Machine is waiting for quarter...
.
You inserted a quarter.
Quarter returned.
You turned but there's no quarter.
You need to pay first.
Mighty Gumball, Inc.
Inventory: : 4
Machine is waiting for quarter...
.
You inserted a quarter
You turned...
.
A gumball comes rolling out out of the slot.
You inserted a quarter
You turned...
.
A gumball comes rolling out out of the slot.
You haven't inserted a quarter.
Mighty Gumball, Inc.
Inventory: : 2
Machine is waiting for quarter...
.
You inserted a quarter
You can't insert another quarter.
You turned...
.
A gumball comes rolling out out of the slot.
You inserted a quarter
You turned...
.
A gumball comes rolling out out of the slot.
Oops, out out of gumballs!!
You can't insert a quarter, the machine is sold out.
You turned, but there are no gumballs.
No gumball dispensed.
Mighty Gumball, Inc.
Inventory: : 0
Machine is sold out.out.Now that we have separated the states, it is going to be much easier to extend the functionality of either existing states or new states.
Call ReleaseBall.
If the machine's count is greater than 0, assign the current state to the no quarter state.
Otherwise, print out "Oops, out of gumballs!" and assigns the current state to the sold out state.
Store a random number in the a local variable named winner.
int winner = this.random.Next(10);If the winner variable is 0 and the machine's count is greater than 1, assign the current state to the winner state.
Otherwise, assign the current state to the sold state.
Cut and paste the call that already existed otherwise the current state will always be the sold state.paste the call that already existed otherwise the current state will always be the sold state.GumballMachine gumballMachine = new GumballMachine(5);
Console.WriteLine(gumballMachine.ToString());
gumballMachine.InsertQuarter();
gumballMachine.TurnCrank();
Console.WriteLine(gumballMachine.ToString());
gumballMachine.InsertQuarter();
gumballMachine.TurnCrank();
gumballMachine.InsertQuarter();
gumballMachine.TurnCrank();
gumballMachine.InsertQuarter();
gumballMachine.TurnCrank();
Console.WriteLine(gumballMachine.ToString());
Console.Read();We suggest stepping through the code but aren't going to explicitly do it here.

Since the winner is random it may take you several runs to get a winning result.
Mighty Gumball, Inc.
Inventory.
Inventory: : 5
Machine is waiting for quarter...
.
You inserted a quarter
You turned...
.
A gumball comes rolling out out of the slot.
Mighty Gumball, Inc.
Inventory: : 4
Machine is waiting for quarter...
.
You inserted a quarter.
You turned...
.
A gumball comes rolling out out of the slot.
You inserted a quarter.
You turned...
.
YOU'RE A WINNER! You get two gumballs for your quarter.
A gumball comes rolling out out of the slot.
A gumball comes rolling out out of the slot.
You inserted a quarter.
You turned...
.
A gumball comes rolling ouf of the slot.
Oops, out out of gumballs!!
Mighty Gumball, Inc.
Inventory: : 0
Machine is sold out.out.Return to each story and verify its acceptance criteria. Preserve the submission format and destination stated in the activity; a reading, setup guide, lab, video demonstration, and oral final may require different evidence.
Define State classes Modify the GumballMachine class to be composed of a particular state. Modify each of the State classes to handle the various behaviors. Modify the GumballMachine class. Check Your Work: Add a WinnerState to the gumball machine.