Summary
Pattern Name | State Pattern |
Pattern Type | Behavioral Pattern |
Scope | Object |
Other Names | Objects for States |
Tagline | Change object behavior on state change |
Use cases | When we want to use a different behavior of an object depending on a certain state |
Related Patterns | Flyweight Strategy |
Difficulty Level | Medium |
Implementations |
Definition
In State pattern, an object (context object) changes its behavior when a certain internal state is changed. On state change the context object will change its behavior completely- like for performing a certain operation the context object will use different objects when the state is changed.
This state change is managed internally so the client which is using the context object might not be aware of the state change.
State pattern can increase the number of classes used for the implementation. That would make the maintenance of the system difficult.
Use Cases
Here are the cases when we need to use the State pattern-
- When the behavior of an object depends on a certain state, and on that state changes the behavior needs to be changed at run-time.
- When there are heavy multipart operations that depend on the object state.
Implementation
State pattern has 3 elements.
- Context: class which holds the state. The behavior of this object is changed on state change.
- State Interface: interface (or abstract class) for the state classes.
- Concrete State Class: classes that are used by the context class. The context object will use any of these class object based on the state.
Follow the steps below to implement State pattern:
- Create an interface or abstract class for the state. Declare a few functions.
- Create multiple classes and implement the state interface. Implement the functions. Maintain a variable to hold the context so that can be used from the state when required.
- Create context class. Implement methods to set and get the state. Add methods to perform actions, in the function call functions from the state.
Examples
Example #1: Simplest State Pattern
Here is the simplest example of State pattern
States
The state is an abstract class, which accepts a context object in constructor. When set, it will store a reference to the context and also will call the setState method of the context and pass current object.
Concrete state classes extends the state class, and implements the operation methods.
// State Interface (Abstract class in this case)
abstract class State
var context: Context
constructor(contextParam: Context)
context = contextParam
context.setState(this)
end constructor
abstract void actionOne()
abstract void actionTwo()
end class
// Concrete State One
class ConcreteStateOne extends State
constructor(contextParam: Context)
super(context)
end constructor
method actionOne()
output "Calling 'actionOne' of - 'ConcreteStateOne'"
end method
method actionTwo()
output "Calling 'actionTwo' of - 'ConcreteStateOne'"
end method
end class
// Concrete State Two
class ConcreteStateTwo extends State
constructor(contextParam: Context)
super(context)
end constructor
method actionOne()
output "Calling 'actionOne' of - 'ConcreteStateTwo'"
end method
method actionTwo()
output "Calling 'actionTwo' of - 'ConcreteStateTwo'"
end method
end class
Context
Context has a setState method that stores the passed state object. Also, implement methods relevant to the state, these methods will call the methods from the state for performing operations.
// Context
class Context
var state: State
method setState(stateParam: State)
state = stateParam
end method
method getState(): State
return state
end method
method performActionOne()
state.actionOne()
end method
method performActionTwo()
state.actionTwo()
end method
end class
Demo
Create a context object. Then pass that to state objects. That will call the setState from the context and state is set as that state object.
We can call methods from context object, which in turn will call the methods from the state object.
var context: Context = new Context()
new ConcreteStateOne(context)
context.performActionOne()
new ConcreteStateTwo(context)
context.performActionOne()
context.performActionTwo()
Output
Calling 'actionOne' of - 'ConcreteStateOne'
Calling 'actionOne' of - 'ConcreteStateTwo'
Calling 'actionTwo' of - 'ConcreteStateTwo'
Example #2: Order State
Let’s consider another example that is a little complex. We are demonstrating an order processing state.
Order State
// Order State
abstract class OrderState
var context: OrderContext
constructor(contextParam: OrderContext)
context = contextParam
context.setState(this)
end constructor
abstract void process()
end class
// Order Check State
class OrderCheckState extends OrderState
constructor(contextParam: OrderContext)
super(contextParam)
end constructor
method process()
// Write code to process the order
output "Checking the order validity and other information")
context.setState(context.getOrderInProgressState())
end method
end class
// OrderInProgressState.java
class OrderInProgressState extends OrderState
constructor(contextParam: OrderContext)
super(contextParam)
end constructor
method process()
// Write code to process the order
output "Processing the order")
context.setState(context.getOrderDeliverState())
end method
end class
// Order Deliver State
class OrderDeliverState extends OrderState
constructor(contextParam: OrderContext)
super(contextParam)
end constructor
method process() {
// Write code to process the order
output "Delivering the order"
context.setState(context.getOrderReceiveState())
end method
end class
// Order Receive State
class OrderReceiveState extends OrderState
constructor(contextParam: OrderContext)
super(contextParam)
enc constructor
method process() {
// Write code to process the order
output "Order received"
context.setState(null)
end method
end class
Order Context Class
// Order Context
class OrderContext
var state: OrderState
var orderCheckState: OrderState
var orderInProgressState: OrderState
var orderDeliverState: OrderState
var orderReceiveState: OrderState
consctructor()
orderCheckState = new OrderCheckState(this)
orderInProgressState = new OrderInProgressState(this)
orderDeliverState = new OrderDeliverState(this)
orderReceiveState = new OrderReceiveState(this)
// Set the placed state as default
state = orderCheckState
end constructor
method setState(stateParam: OrderState)
state = stateParam
end method
method getState(): OrderState
return state
end method
method getOrderCheckState(): OrderState
return orderCheckState;
end method
method getOrderInProgressState(): OrderState
return orderInProgressState;
end method
method getOrderDeliverState(): OrderState
return orderDeliverState;
end method
method getOrderReceiveState(): OrderState
return orderReceiveState;
end method
method runNextProcess() {
if (state != null)
state.process()
else
output "Order processing complete"
end if
end method
end class
Demo
// Demo
var order: OrderContext = new OrderContext()
order.runNextProcess()
order.runNextProcess()
order.runNextProcess()
order.runNextProcess()
// Trying to process after all steps are complete
order.runNextProcess()
Output
Checking the order validity and other information
Processing the order
Delivering the order
Order received
Order processing complete
Code Implementations
Use the following links to check State pattern implementation in specific programming languages.