Skip to main content

C++ Example

#include <iostream>
#include <typeinfo>
/**
* State Design Pattern
*
* Intent: Lets an object alter its behavior when its internal state changes. It
* appears as if the object changed its class.
*/

/**
* The base State class declares methods that all Concrete State should
* implement and also provides a backreference to the Context object, associated
* with the State. This backreference can be used by States to transition the
* Context to another State.
*/

class Context;

class State {
/**
* @var Context
*/
protected:
Context *context_;

public:
virtual ~State() {
}

void set_context(Context *context) {
this->context_ = context;
}

virtual void Handle1() = 0;
virtual void Handle2() = 0;
};

/**
* The Context defines the interface of interest to clients. It also maintains a
* reference to an instance of a State subclass, which represents the current
* state of the Context.
*/
class Context {
/**
* @var State A reference to the current state of the Context.
*/
private:
State *state_;

public:
Context(State *state) : state_(nullptr) {
this->TransitionTo(state);
}
~Context() {
delete state_;
}
/**
* The Context allows changing the State object at runtime.
*/
void TransitionTo(State *state) {
std::cout << "Context: Transition to " << typeid(*state).name() << ".\n";
if (this->state_ != nullptr)
delete this->state_;
this->state_ = state;
this->state_->set_context(this);
}
/**
* The Context delegates part of its behavior to the current State object.
*/
void Request1() {
this->state_->Handle1();
}
void Request2() {
this->state_->Handle2();
}
};

/**
* Concrete States implement various behaviors, associated with a state of the
* Context.
*/

class ConcreteStateA : public State {
public:
void Handle1() override;

void Handle2() override {
std::cout << "ConcreteStateA handles request2.\n";
}
};

class ConcreteStateB : public State {
public:
void Handle1() override {
std::cout << "ConcreteStateB handles request1.\n";
}
void Handle2() override {
std::cout << "ConcreteStateB handles request2.\n";
std::cout << "ConcreteStateB wants to change the state of the context.\n";
this->context_->TransitionTo(new ConcreteStateA);
}
};

void ConcreteStateA::Handle1() {
{
std::cout << "ConcreteStateA handles request1.\n";
std::cout << "ConcreteStateA wants to change the state of the context.\n";

this->context_->TransitionTo(new ConcreteStateB);
}
}

/**
* The client code.
*/
void ClientCode() {
Context *context = new Context(new ConcreteStateA);
context->Request1();
context->Request2();
delete context;
}

int main() {
ClientCode();
return 0;
}
Context: Transition to 14ConcreteStateA.
ConcreteStateA handles request1.
ConcreteStateA wants to change the state of the context.
Context: Transition to 14ConcreteStateB.
ConcreteStateB handles request2.
ConcreteStateB wants to change the state of the context.
Context: Transition to 14ConcreteStateA.