Back to: Design Patterns in C# With Real-Time Examples
State Design Pattern Real-time Example in C# – Vending Machine
In this article, I am going to discuss the State Design Pattern Real-time Example in C# – Vending Machine. Please read our previous article where we discussed State Design Pattern in C#with examples.
Vending Machine:
The Vending machine is one of the best real-time examples of the State Design Pattern. For example, you want to buy one product (Let say Pepsi) from the vending machine. Then what you have to do is, you have to select the product which is nothing but Pepsi and then you have to insert the money. Once you did that, then the vending machine will dispense the product. This is how the Vending machine works in real-time.
Please have a look at the following diagram. Let us assume that the internal state of the Vending machine is Money Not Inserted and Product Not Selected. Then what are all the operations you can perform on the Vending Machine? You can select the product and insert the money but you cannot get the product from the vending machine.
Once you select the product and insert the money the state of the Vending machine changed from Money Not Inserted and Product Not Selected to Money Inserted and Product Selected State. Once the state change to Money Inserted and Product Selected, then what the Vending will do is, it will give you the product as well as the balance amount if any.
This is how the Vending Machine works and based on the internal state the behavior of the vending machine will change.
Implementation of Vending Machine using State Design Pattern in C#:
Step1: Creating the State Interface
Create an interface with the IVendingMachineState.cs and then copy and paste the following code in it. Here we created the interface with two methods i.e. SelectProductAndInsertMoney and DispenseProduct.
using System; namespace StatePattern { public interface IVendingMachineState { void SelectProductAndInsertMoney(int amount, String productName); void DispenseProduct(); } }
Step2: Creating the Concrete States
The Vending machine has basically two internal states i.e. NoMoneyState and HasMoneyState. So, we need to create two concrete state classes by implementing the IVendingMachineState interface.
NoMoneyState:
Create a class file with the name NoMoneyState.cs and then copy and paste the following code in it. Here, we implement IVendingMachineState interface methods.
using System; namespace StatePattern { public class NoMoneyState : IVendingMachineState { public void DispenseProduct() { Console.WriteLine("Vending Machine cannot dispense product because money is not inserted and product is not selected"); } public void SelectProductAndInsertMoney(int amount, string productName) { Console.WriteLine(amount + "Rs has been inserted and " + productName + " has been selected"); } } }
HasMoneyState
Create a class file with the name HasMoneyState.cs and then copy and paste the following code in it. This class also implements the IVendingMachineState interface and provide the implementation for the two methods.
using System; namespace StatePattern { public class HasMoneyState : IVendingMachineState { public void DispenseProduct() { Console.WriteLine("Vending Machine dispensed the product "); } public void SelectProductAndInsertMoney(int amount, string productName) { Console.WriteLine("Already Vending machine has money and product selected, So wait till it finish the current dispensing process"); } } }
Step3: Creating the Context object
Create a class with the name VendingMachine and then copy and paste the following code in it. The following is self-explained so please go through the comment lines.
using System; namespace StatePattern { public class VendingMachine : IVendingMachineState { //Createing a variable to maintain the internal state public IVendingMachineState vendingMachineState { get; set; } //Initially the vending machine has NoMoneyState public VendingMachine() { vendingMachineState = new NoMoneyState(); } public void SelectProductAndInsertMoney(int amount, string productName) { vendingMachineState.SelectProductAndInsertMoney(amount, productName); // Money has been inserted so vending Machine internal state // changed to 'hasMoneyState' if (vendingMachineState is NoMoneyState) { vendingMachineState = new HasMoneyState(); Console.WriteLine("VendingMachine internal state has been moved to : " + vendingMachineState.GetType().Name); } } public void DispenseProduct() { vendingMachineState.DispenseProduct(); // Product has been dispensed so vending Machine changed the // internal state to 'NoMoneyState' if (vendingMachineState is HasMoneyState) { vendingMachineState = new NoMoneyState(); Console.WriteLine("VendingMachine internal state has been moved to : " + vendingMachineState.GetType().Name); } } } }
Step4: Client
Modify the Main method as shown below.
using System; namespace StatePattern { class Program { static void Main(string[] args) { // Initially Vending Machine will be 'noMoneyState' VendingMachine vendingMachine = new VendingMachine(); Console.WriteLine("Current VendingMachine State : " + vendingMachine.vendingMachineState.GetType().Name + "\n"); vendingMachine.DispenseProduct(); vendingMachine.SelectProductAndInsertMoney(50, "Pepsi"); // Money has been inserted so vending Machine internal state // changed to 'hasMoneyState' Console.WriteLine("\nCurrent VendingMachine State : " + vendingMachine.vendingMachineState.GetType().Name + "\n"); vendingMachine.SelectProductAndInsertMoney(50, "Fanta"); vendingMachine.DispenseProduct(); // Product has been dispensed so vending Machine internal state // changed to 'NoMoneyState' Console.WriteLine("\nCurrent VendingMachine State : " + vendingMachine.vendingMachineState.GetType().Name); Console.Read(); } } }
Output:
The task for You:
This real-time example is a task for you guys. I will explain the concept with the diagram and I expect you guys to do the program implementation and provide your code in the comment section.
Real-Time Example: TV Remote
TV Remote control is one of the best examples of the State Design Pattern. Using the TV Remote Control we can switch On the TV and switch off the TV. That means the Remote control internally maintains two states (i.e. On and Off).
For example, when the internal state is On it will on the TV as shown below.
Similarly, when the state is Off it will off the TV as shown below.
In the next article, I am going to discuss the Template Design Pattern in C# with real-time examples. Here, in this article, I try to explain the Vending Machine Implementation using the State Design Pattern in C#. I hope you enjoy this State Design Pattern Real-time Example in C# article.
Hi, thank you for your tutorial, and these are always helpful for me. Here is my work, please look at this.
using System;
namespace StateDemo
{
public interface IRemoteControll
{
void TurnOn();
void TurnOff();
}
public class StateTurnOn : IRemoteControll
{
public void TurnOn()
{
Console.WriteLine(“TV is already turned on. Nothing to do.”);
}
public void TurnOff()
{
Console.WriteLine(“TV is successfully turned off.”);
}
}
public class StateTurnOff : IRemoteControll
{
public void TurnOn()
{
Console.WriteLine(“TV is successfully turned on.”);
}
public void TurnOff()
{
Console.WriteLine(“TV is already turned off. Nothing to do.”);
}
}
public class RemoteController:IRemoteControll
{
private IRemoteControll rState;
private IRemoteControll stateTurnOn = new StateTurnOn();
private IRemoteControll stateTurnOff = new StateTurnOff();
public RemoteController()
{
rState = new StateTurnOff();
}
public void TurnOn()
{
rState.TurnOn();
if (rState is StateTurnOff)
{
rState = stateTurnOn;
}
}
public void TurnOff()
{
rState.TurnOff();
if (rState is StateTurnOn)
{
rState = stateTurnOff;
}
}
}
}
using System;
namespace StateDemo
{
class Program
{
static void Main(string[] args)
{
IRemoteControll remoteControll = new RemoteController();
remoteControll.TurnOff();
remoteControll.TurnOn();
remoteControll.TurnOff();
remoteControll.TurnOff();
remoteControll.TurnOn();
}
}
}
The example of this article accumulates the state objects in the memory. Your example solved the problem. Another example also creates a new instance whenever it changes the state. See below :
https://www.dofactory.com/net/state-design-pattern
I am confused. Did they intend it? What is the advantage of creating new instances if they are not stored as logging or command?