State Design Pattern
Overview
State Design Patterns belongs to the category of Behavioral design pattern. It is used to allow an object to modify its behavior based on the changes in its internal state. It makes the object behave similarly to finite state machines. It makes the object flexible to alter its state without handling a lot of if / else conditions. State pattern ensures loose coupling between the performance of existing states versus the addition of new states.
Note: A Finite State Machine is a model of computation which is based on a hypothetical machine made of one or more states. Only one single state of this machine can be active at a particular time. It means the machine has to do the transition from one state to another in order to reflect different behaviors.
When Will We Need State Design Patterns?
Consider a scenario where a user wants to order food online and get it delivered and the service running at the backend needs to handle the various stages that can be there during the entire process from order initiation and order placing to the final delivery of the order.
One possible way to achieve this can be as follows:
The above pseudo-code is just a glimpse of how complex the scenario can be. This is when we have not handled the scenarios in which cancellations occur in between a particular state, maybe a delay in some process occurs or some other unexpected event occurs.
You can think of if the complexity of the problem increases, managing different stages of the process will become highly complex. Thus, dividing the different stages into different states and managing them individually will simplify the complexity to a very high extent.
The State Design patterns are used mainly in the following 2 scenarios:
- When we need to change the behavior of an object based on modifications in the object's internal state and handling it requires applying a lot of conditional statements.
- When the addition of new states need not affect the behavior of existing states. In other words, the state's pattern is useful when state-specific behavior can be determined independently.
How Does the State Design Pattern Work?
In the State Design Pattern, we create a generic structure of a state in the form of an interface, which declares some behaviors/actions of any particular state. This interface can be used to create specific individual state classes so that those concrete state can define their own specific behavior implementations.
A context class is created which has a state object associated with it. This state object is used to update the behavior of the context object, as the state is altered.
Note: State Pattern ensures loose coupling between the performance of the existing states versus the addition of new states because it segregates the State Class Definition logic by implementing a generic interface from the State Class Object's utility logic and the context object's state-changing logic.
Structure of State Design Pattern
Here,
- FoodOrder is the context class that encapsulates a FoodOrderState and its other attributes and functions. The state associated with this context class can change dynamically at runtime.
- FoodOrderState is an interface that declares the behavior of the concrete child state classes.
- OrderInitiatedState provides a complete implementation of generic behavior declared in the FoodOrderState interface specific to the requirements of order initiation.
- OrderPlacedState provides a complete implementation of generic behavior declared in the FoodOrderState interface specific to the requirements of order placing.
- FoodPreparationState provides a complete implementation of generic behavior declared in the FoodOrderState interface specific to the requirements of Food Preparation.
- WaitingToBePickedState provides a complete implementation of generic behavior declared in the FoodOrderState interface specific to the requirements of waiting before picking of the order.
- OutForDeliveryState provides a complete implementation of generic behavior declared in the FoodOrderState interface specific to the requirements of the delivery process.
- DeliveredState provides a complete implementation of generic behavior declared in the FoodOrderState interface specific to the requirements of the post delivery state.
Implementation of State Design Pattern
Here, we are going to take an example of a Food Ordering System.
- Define a FoodOrder class which will act as our context class.
- Define an interface for the state(s) named FoodOrderState, with the necessary declarations of the required functions.
- Define all the concrete state classes which will implement the FoodOrderState interface. In this case, the concrete classes are: OrderInitiatedState, OrderPlacedState, FoodPreparationState, WaitingToBePickedState, OutForDeliveryState, DeliveredState.
- Finally, define a demo class named FoodOrderingDemo which will handle the creation of a FoodOrder object and the transition among the FoodOrderState(s).
Pseudocode for tate Design Pattern
- Create a State interface or a State class that has only declarations of the required methods.
- Create the FoodOrder class whose behavior needs to be tracked and modified in different Food Order States.
- Create Concrete Classes of all the different states implementing the FoodOrderState interface by providing the respective definitions of the declared methods according to different individual states.
- Create a class FoodOrderingDemo that contains the main driver function which creates the FoodOrder and tracks the change in behavior when the FoodOrderState changes.
Output(s):
Java Code
Output (Java):
C++ Code
Output (C++):
Python Code
Output (Python):
Pros and Cons of State Design Pattern
Pros:
- Whenever we want to alter the behavior of an object by changing the internal state, and we do not want to handle a lot of if / else complex conditional blocks, then in that state design pattern can be highly advantageous.
- Whenever we want to add new states so that new behaviors can be generated in the application and we do not want to impact the existing behaviors pertaining to the previously defined states, in that case also State design pattern is the best bet.
- State design pattern is beneficial in implementing a polymorphic behavior, as the same function call is performing different tasks each time.
Cons:
- State Design pattern requires you to write a lot of code. The addition of new states requires more code, which makes code management a little difficult.
- When there are only a few states, then applying the state pattern just increases the unnecessary maintenance of a lot of code.
Difference Between State Design Pattern and Strategy Design Pattern
In State Design Pattern, each state is connected to another state so that a flow can be created from an initial state to some final state as in finite state machines. State patterns allow us to switch from one state to another dynamically at runtime so that the behavior of the context object can change. State pattern allows different states to be dependent on each other in a flow so that the behavior of the context class can be changed from one state to another. Whereas, Strategy Design Pattern is used to provide a better alternative to subclassing, i.e, if a user wants to decide on a particular strategy for doing some work like deciding on a sorting algorithm to be executed from a list of available sorting algorithms on some array, or choosing an operation to perform on 2 numbers like addition or subtraction or multiplication, etc. Strategy pattern allows us to select a particular strategy dynamically at runtime to do some task on the provided input. Different strategies are independent and unaware of each other.
FAQs:
Q. Which Design Patterns are similar to State Design Patterns and why?
A. The state pattern is very much similar to the strategy design pattern. In fact, the State pattern can be considered as an extension of the Strategy pattern. Both patterns are based on composition as they both encapsulate one object into another object and they change the behavior of the context class by delegating some work to helper objects.
Q. What is the main difference between State Design
A. Pattern and Strategy Design Pattern? The main difference between state pattern and strategy pattern is the intent. State pattern allows you to modify the behavior of the object at runtime in a flow of connected states behaving differently. Whereas Strategy pattern allows you to choose between algorithms or strategies at runtime, such that these algorithms/strategies are independent and unaware of each other.