C# Design Patterns: State
Thanks for visiting this article. Please scroll down for the bite-sized explanation of this pattern.
Definition
The State design pattern is a behavioural design pattern that encourages encapsulating state-specific behaviour into separate classes instead of defining states in a monolithic class with conditionals.
This approach makes the code more maintainable and scalable, especially when adding, modifying, or removing states.
When to use?
This pattern is suitable for the following cases:
✅ When an object has different behaviour depending on its state,
✅ When the number of states may frequently change and can extend over time.
When not to use?
❌ When the states of an object are fixed and do not need to change or rarely change over time.
❌ When the number of states is manageable and does not need the behaviours, encapsulated in multiple classes.
Example
Since this pattern is suitable for objects with state-specific behaviours, let’s try to understand this by a simple e-commerce “Order”.
An Order can be created, processed, shipped, delivered and cancelled (only when the order is still under processing).
Let’s create an Order class having an enum called OrderState and a property State to keep track of the current state.
For the sake of less code, we will consider a single order instance to deal with…you are welcome to introduce an
IDfor extending the behaviours based on multiple ordersIDsfor each state
Note: The code examples below are written as part of this blog and could contain syntax errors. The main goal of these examples is to deliver an understandable concept.
We will call the required behaviours by the following method names:
NewOrder(can be replaced by the constructor),ProcessOrder,ShipOrder,DeliverOrder,- and
CancelOrder.
These methods will define the behaviours based on the current order state and will be responsible for updating the state when required.
Finally, let’s call these methods from our client Shop class, to have an order created and delivered 😏
This implementation covers the common order behaviours, any e-commerce platform nowadays has to provide. 💁
The problem with the above approach
❌ Tight Coupling: All state-related behaviour is in one class.
❌ Complexity: Adding new states or changing state behaviour requires modifying the existing class.
❌ Maintenance: Difficult to maintain as the number of states and transitions grows.
Get Biswajit Sahoo’s stories in your inbox
Join Medium for free to get updates from this writer.
But as the e-commerce market is ever-growing, we can imagine customers wanting more-n-more flexibility with their orders, for example:
- allowing them to return an ordered product,
- or even modify an ordered product and so on…
As any senior developer, now you need to modify your app’s functionality to accommodate the new behaviours and states for an Order 😤 keeping in mind the code quality and ability to scale it afterwards. ⛳️
And that clearly cannot be possible by jamming all the possible states in one single-order class (you know where this is going 😙).
Hence comes the State design pattern to rescue.
Implementing the State Pattern
The State design pattern states that if you have many state-dependent behaviours to manage for an object, then shift them to their respective classes and have them automatically handle their behaviours.
Before implementing the state pattern, let’s understand the components required:
- State Abstraction / Interface — typically declares methods representing the state-specific behaviour of the object.
- Concrete classes — These refer to the individual classes we are going to create for each of the possible states and implement the State abstraction/interface.
- Context class — This is the object class itself which maintains a reference to its current state. It will act as an interface for clients to interact with and delegate state-specific behaviour to the current state object. (will make more sense as you read along 😃 )
We will call the interface, IOrderState.
With the interface defined, let’s create the individual states (Concrete classes) and move the state-specific behaviours within the respective classes,
With the concrete states created, you may be wondering what is this order and how we set the state on it using order.SetState(IOrderState) ?
Well, that’s the final context class we are going to create, called Order.
And all, we have to do now…is to use the same Shop class (client) we had created earlier,
With the implementation complete, you can see the clear advantage of this design pattern over the traditional approach:
- ✅ Encapsulation: State-specific behaviour is encapsulated in individual state classes.
- ✅ Ease of Maintenance: Adding or modifying states does not affect the
Orderclass. - ✅ Flexibility: Easily add new states or change the behaviour of existing states.
But this design pattern is not all shiny 🌟 and contains some obvious disadvantages ⛅️, like:
- ⚠️ Increased Number of Classes: More classes are created for each state.
- ⚠️ ️Initial Complexity: Setting up the pattern requires more initial effort.
- ⚠️ State awareness: Concrete state classes need to be aware of the other state types, for them to set the correct state when needed.
something to be kept in mind when choosing this pattern to implement.
The above disadvantages can be mitigated by doing some additional work.
And that completes this example of explaining how and when to use the State design pattern in your project. 😄
Hope this helped with giving you some clarity on how this pattern can be implemented and used in a real-world scenario.
On the last note. If you like the article please do like and share, and also feel free to provide your valuable comments and feedback.










