状态模式(State)-设计模式(九)

1、作用

允许一个对象在其内部状态改变时改变它的行为。

每个人、事物在不同的状态下会有不同的表现,而一个状态在不同的表现下会转换为另一个状态。

举个例子:
我们去买一杯奶茶,有热饮、冷饮、和常温三种可供选择,我们首先选择了常温的,在奶茶开始制作的时,擡头看了看天气,现在烈日炎炎,想想一杯冰凉的奶茶是不是能够按下躁动的心,因此立马决定告诉店员,我需要改成冷饮,而店员呢,也就需要改变奶茶的制作流程。

2、解决的问题

我们在搬砖中经常会遇到几种状态的选择,比如简单的鼠标的三种状态,遇到这种情况时,通常的方式是使用switch-case语句实现,这种实现方式简单粗暴,很香。但是,如果有十几种状态,甚至几十种呢,如果还是像往常一样写switch-case语句,维护一大组这样的语句是异常困难并且很容易出错的。就算强悍的我们维护了这样一大组的switch-case,后续如果有新增加的状态和行为,就需要对这段代码重新改造增加,扩展性和维护会变得很差。

状态模式的出现很好的解决了这种情况,我们有很多的状态,每一个状态实现一个行为,状态改变时,对应的行为也就会跟着改变,这样我们在整个代码中就维护了一个状态。

#include<iostream>
using namespace std;

class Context;
class State
{
public:
	virtual ~State(){}
	virtual void Handle(Context *pContext)=0;
};
class Context
{
	public:
	Context(State* pState):m_pState(pState){}
	~Context()
	{
		delete m_pState;
		m_pState = NULL;
	}
	
	void Request()
	{
		if(NULL != m_pState)
		m_pState->Handle(this);
	}
	
	void ChangeState(State* pState)
	{
		if(NULL != m_pState)
		{
			delete m_pState;
			m_pState = NULL;
		}
		m_pState = pState;
	}
private:
	State *m_pState;
};

class HotDrinks : public State
{
public:
	void Handle(Context* pContext);
};


class ColdDrinks : public State
{
public:
	void Handle(Context* pContext);
};

void HotDrinks::Handle(Context* pContext)
{
	cout << "Make a hot drink ..." << endl;
	
	if(NULL != pContext)	//突然改变 需要 冷饮 
	{
		pContext->ChangeState(new ColdDrinks());
	}
}
void ColdDrinks::Handle(Context* pContext)
{
	cout << "Make a cold drink ..." << endl;
	if(NULL!=pContext)
	{
		pContext->ChangeState(new HotDrinks());
	}
		
}
int main()
{
	Context* pContext = new Context(new HotDrinks());	//首先委会一份热饮的状态 
	pContext->Request();
	pContext->Request();	//改变状态 ,要冷饮 
	
	delete pContext;
	pContext = NULL;
	return 0;
}

通过上面的例子我们可以看出,对于一杯奶茶来说,中间可以改变自己的状态,当然现实生活中奶茶并不是可以随便改变的,基本上是一锤定音的且不可更改的,要不然谁买单呢?

3、思考

  • 整个过程中state的数量可能会很多,是不是做一个管理所有state的类StateManager会比较好呢,这个类统一管理所有state的切换,外界需要切换状态时只需要向该类提交申请就好。
  • 整个状态的切换过程中,我们不停的进行了状态的申请和释放,上面的例子状态只切换两次,就进行了3次的对象申请和释放,因此,state应该实现为一个singleton,避免申请时的内存和时间的消耗

4、UML 结构图
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章