Skip to content

Latest commit

 

History

History
143 lines (108 loc) · 4.93 KB

state.md

File metadata and controls

143 lines (108 loc) · 4.93 KB

State

The State design pattern is a behavioral design pattern that allows an object to alter its behavior when its internal state changes. It is useful in situations where an object needs to change its behavior based on its internal state, and the number of possible states is large or dynamic.

The State pattern involves two key components: the Context and the State. The Context represents the object whose behavior is affected by its internal state. It contains a reference to the current state object. The State interface defines a set of methods that encapsulate the behavior associated with a particular state.

Here's how the State pattern works:

  1. The Context maintains a reference to a State object that represents its current state.

  2. The State interface defines a set of methods that encapsulate the behavior associated with each state.

  3. The Context delegates the execution of specific operations to the current State object.

  4. When the Context's internal state changes, it updates its reference to the appropriate State object.

  5. The State objects handle requests from the Context and may also update the Context's state if necessary.

By using the State pattern, the behavior of an object can be changed dynamically at runtime by simply changing its internal state. This approach promotes loose coupling between the Context and the State objects, as each state encapsulates its own behavior.

The State pattern is particularly useful when you have an object with complex behavior that depends on its state and when you want to avoid using large conditional statements or switch statements to handle different states. It promotes code modularity, flexibility, and extensibility by allowing new states to be added without modifying existing code.

Let's consider a vending machine as a real-world example of the State design pattern in C#. A vending machine can have different states based on its internal condition, such as "Ready", "OutOfStock", or "Dispensing".

First, we define the State interface that declares methods for various vending machine states:

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

Next, we implement different states as concrete classes that implement the State interface:

public class ReadyState : IVendingMachineState
{
    public void InsertCoin()
    {
        Console.WriteLine("Coin inserted. Please select a product.");
    }

    public void SelectProduct(string product)
    {
        Console.WriteLine("Product selected: " + product);
    }

    public void DispenseProduct()
    {
        Console.WriteLine("Please insert a coin and select a product.");
    }
}

public class OutOfStockState : IVendingMachineState
{
    public void InsertCoin()
    {
        Console.WriteLine("Sorry, the machine is out of stock.");
    }

    public void SelectProduct(string product)
    {
        Console.WriteLine("Sorry, the machine is out of stock.");
    }

    public void DispenseProduct()
    {
        Console.WriteLine("Sorry, the machine is out of stock.");
    }
}

public class DispensingState : IVendingMachineState
{
    public void InsertCoin()
    {
        Console.WriteLine("Please wait, currently dispensing a product.");
    }

    public void SelectProduct(string product)
    {
        Console.WriteLine("Please wait, currently dispensing a product.");
    }

    public void DispenseProduct()
    {
        Console.WriteLine("Product dispensed. Enjoy!");
    }
}

Then, we create the Context class, which represents the vending machine and maintains a reference to the current state:

public class VendingMachine
{
    private IVendingMachineState currentState;

    public VendingMachine()
    {
        currentState = new ReadyState();
    }

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

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

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

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

Finally, we can use the vending machine as follows:

VendingMachine vendingMachine = new VendingMachine();

vendingMachine.InsertCoin(); // Output: Coin inserted. Please select a product.

vendingMachine.SetState(new OutOfStockState());
vendingMachine.SelectProduct("Coke"); // Output: Sorry, the machine is out of stock.

vendingMachine.SetState(new ReadyState());
vendingMachine.InsertCoin(); // Output: Coin inserted. Please select a product.
vendingMachine.SelectProduct("Snacks"); // Output: Product selected: Snacks
vendingMachine.DispenseProduct(); // Output: Product dispensed. Enjoy!

In this example, the behavior of the vending machine changes based on its internal state. The State design pattern allows us to encapsulate each state's behavior in separate classes, making the code more modular and flexible.