C++设计模式——状态模式(state pattern)

一、原理讲解

别名状态对象(object for state)。

1.1意图

允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。

1.2应用场景

  • 一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为;
  • 一个操作中含有庞大的分支语句的条件语句,且这些分支依赖于该对象的状态;

1.3结构图(UML图)

C++设计模式——状态模式(state pattern)_第1张图片

1.4代码实现步骤

a1 定义一个状态接口类IState,定义一个接口函数handle();
a2 定义一个具体状态类ConcreteState,实现接口函数handle(),处理完后用形参传入上下文类对象改变当前状态;
a3 定义一个上下文类Context,定义两个接口函数request()和changeState(),request()调用具体状态类处理函数;

二、实现代码

StatePattern.cpp

#include 

using namespace std;

#define DELETE(pointer) delete pointer; pointer=nullptr

class Context;

class IState // 抽象状态接口类
{
public:
	virtual ~IState() {}
	virtual void handle(Context *context) = 0; // 传入上下文类接口,处理完后改变当前状态(可以理解为设置为下一状态)
};

class ConcreteState1 : public IState // 具体状态接口类1
{
public:
	void handle(Context *context) override; // 要在类Context声明后面定义,否则会提示使用了未定义“Context”
};

class ConcreteState2 : public IState // 具体状态接口类2
{
public:
	void handle(Context *context) override;
};

class ConcreteState3 : public IState // 具体状态接口类3
{
public:
	void handle(Context *context) override;
};

class Context
{
	IState *state;
public:
	Context(IState *state) :state(state) {}
	~Context() { if (this->state) DELETE(this->state); } // 实现自动内存管理,防止内存泄漏}
	void request() { state->handle(this); } // 委托处理函数
	void changeState(IState *state) { // 改变状态
		if (this->state) DELETE(this->state); // 实现自动内存管理,防止内存泄漏
		this->state = state; } 

};

void ConcreteState1::handle(Context *context) 
{
	cout << "ConcreteState1::handle()" << endl; // 添加处理这个状态的逻辑功能代码
	context->changeState(new ConcreteState2);
}

void ConcreteState2::handle(Context *context)
{
	cout << "ConcreteState2::handle()" << endl; // 添加处理这个状态的逻辑功能代码
	context->changeState(new ConcreteState3);
}

void ConcreteState3::handle(Context *context)
{
	cout << "ConcreteState3::handle()" << endl; // 添加处理这个状态的逻辑功能代码
	context->changeState(new ConcreteState1);
}

void doStatePattern()
{
	// 初始化Context对象,Context内部实现具体状态ConcreteState内存管理,不需要手动释放
	Context *context = new Context(new ConcreteState1());
	
	context->request(); // 状态请求
	context->request();
	context->request();
	context->request();

	DELETE(context); // Context对象没有实现自动内存管理,需要手动释放
}

mian.cpp

#include 

extern void doStatePattern();

int main()
{
	doStatePattern();

	system("pause");
	return 1;
}

C++设计模式——状态模式(state pattern)_第2张图片

三、总结

状态模式在代码实现上跟策略模式差不多,两者相同点都是用上下文类函数Context::request()委托实现具体状态处理函数state->handle();不同点在于状态模式客户感兴趣的是当一个对象的状态发生改变时会影响其行为动作,而策略模式不关注客户的状态只关注算法框架的实现和逻辑分离。可以看出,状态模式是一种特殊的策略模式,而策略模式不一定是状态模式。
优点:功能实现代码和逻辑代码解耦(或者说分离);子类职责划分清晰,易于扩展额维护修改;
缺点:每个switch-case分支都会生成一个独立的子类,导致子数量庞大;

四、参考内容

C++状态模式详解–设计模式(15)
状态模式(state)C++实现
设计模式-状态模式 C++实现
陈建忠设计模式(参考:哔哩哔哩C++设计模式!!!)
Erich Gamma,Richard Helm.《设计模式 可复用面向对象软件的基础》[M].机械工业出版社,2019:

你可能感兴趣的:(设计模式,c++,设计模式,状态,模式,state)