State Design Pattern in C#

The State design pattern is a behavioral design pattern that allows an object to alter its behavior when its internal state changes. This pattern is useful when an object’s behavior depends on its state, and it needs to transition between different states.

Let’s create an example of the State pattern in C# with a use case. Consider a simple vending machine that dispenses different items based on its current state (e.g., idle, selecting a product, dispensing, out of stock).

Define the states as separate classes:

// State interface
public interface IVendingMachineState
{
    void InsertCoin();
    void SelectProduct(string product);
    void DispenseProduct();
}

// Concrete state classes
public class IdleState : IVendingMachineState
{
    private VendingMachine vendingMachine;

    public IdleState(VendingMachine vendingMachine)
    {
        this.vendingMachine = vendingMachine;
    }

    public void InsertCoin()
    {
        Console.WriteLine("Coin inserted. Please select a product.");
        vendingMachine.SetState(vendingMachine.GetProductSelectionState());
    }

    public void SelectProduct(string product)
    {
        Console.WriteLine("Please insert a coin first.");
    }

    public void DispenseProduct()
    {
        Console.WriteLine("No product selected.");
    }
}

public class ProductSelectionState : IVendingMachineState
{
    // Similar to the IdleState, but with different behavior
    // ...

    public void InsertCoin()
    {
        // ...
    }

    public void SelectProduct(string product)
    {
        // ...
    }

    public void DispenseProduct()
    {
        // ...
    }
}

// More state classes (e.g., DispensingState, OutOfStockState) can be added as needed.

Create the VendingMachine class that uses these states:

public class VendingMachine
{
    private IVendingMachineState currentState;

    public VendingMachine()
    {
        currentState = new IdleState(this);
    }

    public void SetState(IVendingMachineState state)
    {
        currentState = state;
    }

    public IVendingMachineState GetCurrentState()
    {
        return currentState;
    }

    // Define methods for vending machine operations
    public void InsertCoin()
    {
        currentState.InsertCoin();
    }

    public void SelectProduct(string product)
    {
        currentState.SelectProduct(product);
    }

    public void DispenseProduct()
    {
        currentState.DispenseProduct();
    }
}

Now, you can use the VendingMachine with different states:

class Program
{
    static void Main(string[] args)
    {
        VendingMachine vendingMachine = new VendingMachine();

        vendingMachine.InsertCoin(); // Insert a coin
        vendingMachine.SelectProduct("Soda"); // Select a product
        vendingMachine.DispenseProduct(); // Dispense the product

        // You can transition between states and perform operations accordingly
    }
}

In this example, the State design pattern allows the vending machine to change its behavior based on its internal state. Different states (IdleState, ProductSelectionState, etc.) define how the vending machine responds to various operations, promoting flexibility and maintainability in the code.