The state design pattern is used when a class needs to change its behavior based on its current state. For example, an object of the Car
class has a horsepower of 150, and it increases to 200 after turning on turbo mode.
The default approach to implement this behavior is to create a member variable (state
) and change its value whenever a certain condition is met, or a method is invoked. Afterward, when a state-specific action is to be performed, we can check the current state using if-else conditions and invoke the specific method. However, this will turn out to be a hassle in the long run because another state may be added in the future and, consequently, another if-else statement will have to be added.
The need to add if-else conditions is avoided when the state design pattern is implemented. There are two main classes that make up the state design pattern:
The context class contains a reference (or pointer)of type state, which is an interface. This way, polymorphism can be used to choose the method of the current state. The state can be changed by a method in either a derived state class or in the context class.
There are no interfaces in C++. Therefore, an abstract base class, plus multiple inheritances, are used.
Similarly, in Python, an abstract base class is used instead of an interface. Since the abstract
keyword does not exist in Python, abstract classes are declared using the ABC
module.
#include <iostream>using namespace std;// State abstract class:class State{public:virtual void printState() = 0;};// 'Default' state (singleton):class Default: public State{private:static Default* instance;Default(){}public:static Default* getInstance(){if(instance == nullptr)instance = new Default();return instance;}void printState(){cout << "\nCar is in normal mode. 150 BHP\n";}};Default* Default::instance = nullptr;// 'Turbo' state (singleton):class Turbo: public State{private:static Turbo* instance;Turbo(){}public:static Turbo* getInstance(){if(instance == nullptr)instance = new Turbo();return instance;}void printState(){cout << "\nTurbo mode turned on! 200 BHP\n";}};Turbo* Turbo::instance = nullptr;// Context:class Car{int id;string name;State* currentState;public:Car(int i, string n){id = i;name = n;currentState = Default::getInstance();}void turboOn(){currentState = Turbo::getInstance();}void turboOff(){currentState = Default::getInstance();}void printInfo(){currentState->printState();}void printDetails(){cout << "ID: " << id << ", Name: " << name;}};int main(){// Testing:Car superCar(1, "Maserati");superCar.printDetails();superCar.printInfo();// Turn on turbo:superCar.turboOn();superCar.printInfo();// Turn off turbo:superCar.turboOff();superCar.printInfo();return 0;}
Free Resources