Original Link: https://my.oschina.net/zipu888/blog/549585
1. Overview
State Pattern s are state modes.A simple case:
For automatic doors, there are two states: open and close, if the door is open, if the user presses the open button again, there is no response, if the close key is pressed, the door closes.
switch...case...implementation:
To do this, a State Pattern is introduced, mainly for:
1) A scene in which the behavior of an object depends on its state.
2) Finite-state automata
Class diagram of state:

Manage: Provides service interfaces to client s
State: State abstract base class
State_x: A concrete state class that defines the specific behavior of the corresponding operation in that state
One very important point is who controls state migration, two scenarios:
1) The Manage class is responsible for state migration
2) The State class itself is responsible for state migration
The disadvantage of the former is that adding a new state class is more complex. If there are too many states and the state migration is responsible, the Manage class is too complex. In addition, the Manage class needs to know the specific state class.
The disadvantage of the latter is that each state object must be aware of the existence of its sibling state object, which leads to dependencies among the state subclasses.
2. Examples
The restaurant Waiter has two states: busynes and idle. If the Waiter is busy, it cannot respond to guests'requests for service. If it is in the Idle state, it can respond to guests' requests and set its status as Busyness.
State Pattern s implementation method (the state subclass is responsible for state migration)
Client: service request
Waiter: i am coming
Waiter state change from idle to business
Client: service request
Waiter: i am busy, boss
Client: service request
Waiter: i am busy, boss
State Pattern Implementation 2 (Manage is responsible for state migration)
Client: service request
Waiter: i am coming
Waiter state change from idle to business
Client: service request
Waiter: i am busy, boss
Waiting.....
Client: service request
Waiter: i am busy, boss
Waiting.....
State Pattern s are state modes.A simple case:
For automatic doors, there are two states: open and close, if the door is open, if the user presses the open button again, there is no response, if the close key is pressed, the door closes.
switch...case...implementation:
You can see that states and corresponding operations are managed by the Manage class, and that states and corresponding operations are not isolated and cannot change independently; in addition, if there are too many states, the Manage class code is too complex.const int OPEN = 1; // Door open state const int CLOSE = 2;// door close status class Manage { public: void open() { switch(door.state) { case OPEN : do nothing; break; case CLOSE: open the door; break; default: break; } } }
To do this, a State Pattern is introduced, mainly for:
1) A scene in which the behavior of an object depends on its state.
2) Finite-state automata
Class diagram of state:

State: State abstract base class
State_x: A concrete state class that defines the specific behavior of the corresponding operation in that state
One very important point is who controls state migration, two scenarios:
1) The Manage class is responsible for state migration
2) The State class itself is responsible for state migration
The disadvantage of the former is that adding a new state class is more complex. If there are too many states and the state migration is responsible, the Manage class is too complex. In addition, the Manage class needs to know the specific state class.
The disadvantage of the latter is that each state object must be aware of the existence of its sibling state object, which leads to dependencies among the state subclasses.
2. Examples
The restaurant Waiter has two states: busynes and idle. If the Waiter is busy, it cannot respond to guests'requests for service. If it is in the Idle state, it can respond to guests' requests and set its status as Busyness.
State Pattern s implementation method (the state subclass is responsible for state migration)
Output:#include <iostream> using namespace std; class Waiter { public: Waiter(); void request(); void setCur(class State* state) { _cur = state; } private: State *_cur; }; class State { public: virtual ~State() { } virtual void request(Waiter*) = 0; }; class Busyness_state : public State { public: void request(Waiter*) { cout << "Waiter: i am busy, boss" << endl; } }; class Idle_state : public State { public: void request(Waiter* waiter) { cout << "Waiter: i am coming" << endl; waiter->setCur(new Busyness_state); cout << "Waiter state change from idle to business" << endl; delete this; } }; Waiter::Waiter() { _cur = new Idle_state(); } void Waiter::request() { cout << "Client: service request" << endl; _cur->request(this); } int main() { Waiter waiter; waiter.request(); waiter.request(); waiter.request(); return 0; }
Client: service request
Waiter: i am coming
Waiter state change from idle to business
Client: service request
Waiter: i am busy, boss
Client: service request
Waiter: i am busy, boss
State Pattern Implementation 2 (Manage is responsible for state migration)
Output:#include <iostream> #include <vector> using namespace std; class Waiter { public: Waiter(); void request(); void setCur(class State* state) { if(_cur) { delete _cur; } _cur = state; } private: State *_cur; }; class State { public: virtual ~State() { } virtual bool request() = 0; }; class Busyness_state : public State { public: bool request() { cout << "Waiter: i am busy, boss" << endl; return false; } }; class Idle_state : public State { public: bool request() { cout << "Waiter: i am coming" << endl; return true; } }; Waiter::Waiter() { _cur = new Idle_state(); } void Waiter::request() { cout << "Client: service request" << endl; if(_cur->request()) { setCur(new Busyness_state); cout << "Waiter state change from idle to business" << endl; } else { cout << "Waiting....." << endl; } } int main() { Waiter waiter; waiter.request(); waiter.request(); waiter.request(); return 0; }
Client: service request
Waiter: i am coming
Waiter state change from idle to business
Client: service request
Waiter: i am busy, boss
Waiting.....
Client: service request
Waiter: i am busy, boss
Waiting.....
Reprinted at: https://my.oschina.net/zipu888/blog/549585