一、UML图
二、包含的角色
IState类,接口会声明特定于状态的方法。 这些方法应能被其他所有具体状态所理解, 因为你不希望某些状态所拥有的方法永远不会被调用。
Context类,保存了对于一个具体状态对象的引用, 并会将所有与该状态相关的工作委派给它。 上下文通过状态接口与状态对象交互, 且会提供一个设置器用于传递新的状态对象。
ConcreteState类,会自行实现特定于状态的方法。 为了避免多个状态中包含相似代码, 你可以提供一个封装有部分通用行为的中间抽象类。状态对象可存储对于上下文对象的反向引用。 状态可以通过该引用从上下文处获取所需信息, 并且能触发状态转移。
三、特点
状态模式将所有特定于状态的代码抽取到一组独立的类中。 这样一来, 你可以在独立于其他状态的情况下添加新状态或修改已有状态, 从而减少维护成本。
状态模式会将这些条件语句的分支抽取到相应状态类的方法中。 同时, 你还可以清除主要类中与特定状态相关的临时成员变量和帮手方法代码。
状态模式让你能够生成状态类层次结构, 通过将公用代码抽取到抽象基类中来减少重复。
四、代码实现
IState类
#pragma once
#include <iostream>
class Context;
class IState
{
public:
IState(std::string name) : name_(name) {}
virtual ~IState() {}
virtual void Handle() = 0;
std::string name()
{
return name_;
}
void set_context(Context* context){
context_ = context;
}
protected:
Context *context_;
private:
std::string name_;
};
Context类
#pragma once
#include <iostream>
class Context;
class IState
{
public:
IState(std::string name) : name_(name) {}
virtual ~IState() {}
virtual void Handle() = 0;
std::string name()
{
return name_;
}
void set_context(Context* context){
context_ = context;
}
protected:
Context *context_;
private:
std::string name_;
};
ConcreteState类
#pragma once
#include "Context.h"
class ConcreteState1 : public IState
{
public:
ConcreteState1() : IState("state1") {}
public:
void Handle() override
{
context_->set_state(new ConcreteState2());
std::cout << name() << " do handle: "
<< "change state to " << context_->state()->name() << std::endl;
}
};
class ConcreteState2 : public IState
{
public:
ConcreteState2() : IState("state2") {}
public:
void Handle() override
{
context_->set_state(new ConcreteState3());
std::cout << name() << " do handle: "
<< "change state to " << context_->state()->name() << std::endl;
}
};
class ConcreteState3 : public IState
{
public:
ConcreteState3() : IState("state3") {}
public:
void Handle() override
{
std::cout << name() << " do handle: " << name() << " logic..." << std::endl;
}
};
main
#include "ConcreteState1.h"
int main()
{
IState* s = new ConcreteState1(); //初始化一个状态
Context* c = new Context(s); //初始化一个状态
c->Request();
c->Request();
c->Request();
delete c;
return 0;
}