设计模式学习(二十) 状态模式 State

1.状态模式的定义

 状态模式的官方定义如下:“当一个对象的内在状态改变时允许改变其行为,使得这个对象看起来像是改变了其类。”对这句话的简写,就是“通过用户 的状态来改变对象的行为”。
 通俗来讲,状态模式就是指一个人做同一个事情,由于其状态的不同,得到结果也就不一样。比如今天精神一般,只能搬1000块砖,明天精神很棒,可以搬2000块砖了,后天精神很差,500块砖都搬不了了。这就是所谓的状态不同,导致所做事的成国所不同。

2.状态模式的类图

状态模式类图
 状态模式的类图,可以说是一览无余。Context环境类内部有一个/多个状态State,除了拥有改变和获取当前State状态的函数外,同时拥有对自己其他成员变量的操作函数。State状态类定义了一种抽象的状态,其声明了一个接口Handle,表示了Context环境类需要做的事情的处理方式。ConcreteState实例状态类的通过对Handle接口的实现方式不同,完成了在不同状态下Context对同一件事的实现方式的不同。

  1. Context环境类:这是一个实例类,其内部存储了State状态类作为成员变量,并拥有获取与修改当前自己状态的函数,同时,其也可以自行添加别的成员变量与函数;
  2. State状态类:这是一个抽象类,其内部接口必须定义一个/多个Handle函数,用于表示Context环境类在不同的状态下,都需要去做的一个/多个事情;
  3. ConcreteState实例状态类:其继承自State状态类,通过实例化接口函数Handle,从而完成对不同状态下不同功能的具体实现过程。同时,其与Context环境类呈依赖关系。(需要调用Context环境类的获取与修改当前自己状态的函数)

3.状态模式的代码实现

 本例中,选用一个公司员工Worker来表示Context环境类,State状态类仍保持标准格式,其中的接口函数是work,而ConcreteState则为表示员工上午、中午、下午、晚上以及下班工作状态的ForenoonState、noonState、AfternoonState、NightState以及RestState五个子类表示。
 功能实现则根据当前的时间来判断当前状态需要做什么事情,倘若输入的时间和当前状态时间不匹配,则跳转到下一状态继续判断,以此类推。具体代码如下:

 关于本例的代码,有个关于类的构造顺序的问题想提一下:
 由于本例中,Worker类包含State类为成员变量,而State类又包含Woker类作为函数参数,这样就会导致,即使在类前预声明了类,VS还是会报错。
 以本例举例,在Worker类的构造函数中,将其成员变量初始化为ForenoonState,但是ForenoonState的定义在其之后,此时倘若只是单单的在Worker类前增加class ForenoonState;的声明是无用的。这是因为Woker类中已经使用了ForenoonState的构造函数来实现,而类前声明只能用于定义指针、引用、以及用于函数形参的指针和引用。所以此时类前声明不能实现我们想要的效果。
 而解决方案也非常简单,就是将ForenoonState类的定义放置在Worker类的前方,然后将其中的函数实现放置在后方即可,这样就能保证ForenoonState的构造函数能在Worker类中正常使用了。这也是将多个类放在一个cpp文件里的坏处,正式在软件开发过程中类基本都是一个类一个文件存在的。

#include <iostream>
using namespace std;

class Worker;

class State
{
public:
	virtual void work(Worker *worker) = 0;
};

class ForenoonState : public State
{
	void work(Worker* worker) override;
};

class Worker
{
public:
	Worker() { m_state = new ForenoonState; m_taskfinished = false; }
	double getHour() { return m_hour; }
	void setHour(double hour) { m_hour = hour; }
	void getState() { return m_state->work(this); }
	void setState(State *state) { m_state = state; }
	bool m_taskfinished;
private:
	double m_hour;
	State *m_state;
};

class RestState : public State
{
public:
	void work(Worker* worker) override
	{
		cout << worker->getHour() << "点,我已经完成任务下班啦!" << endl;
	}
};

class NightState : public State
{
public:
	void work(Worker* worker) override
	{
		if (worker->m_taskfinished)
		{
			worker->setState(new RestState);
			worker->getState();
		}
		else
		{
			if (worker->getHour() <= 21 && worker->getHour() > 17.5)
			{
				cout << worker->getHour() << "点,正在晚上加班!" << endl;
			}
			else
			{
				cout << worker->getHour() << "点,任务虽然没完成,但是我还是下班了!" << endl;
			}
		}
	}
};

class AfternoonState : public State
{
public:
	void work(Worker* worker) override
	{
		if (worker->getHour() <= 17.5 && worker->getHour() > 14)
		{
			cout << worker->getHour() << "点,进行下午的工作" << endl;
		}
		else
		{
			worker->setState(new NightState);
			worker->getState();
		}
	}
};

class NoonState : public State
{
public:
	void work(Worker* worker) override
	{
		if (worker->getHour() <= 13.5 && worker->getHour() > 12)
		{
			cout << worker->getHour() << "点,正在午休,请勿打扰!" << endl;
		}
		else
		{
			worker->setState(new AfternoonState);
			worker->getState();
		}
	}
};

void ForenoonState::work(Worker* worker)
{
	if (worker->getHour() <= 9 && worker->getHour() >= 8)
	{
		cout << worker->getHour() << "点,刚进入工作,整理昨天的材料,准备今天的任务" << endl;
	}
	else
	{
		if (worker->getHour() <= 12 && worker->getHour() > 9)
		{
			cout << worker->getHour() << "点,进行上午的工作" << endl;
		}
		else
		{
			worker->setState(new NoonState);
			worker->getState();
		}
	}
}

int main()
{
	Worker* mike = new Worker;
	mike->setHour(8.2);
	mike->getState();
	mike->setHour(11.2);
	mike->getState();
	mike->setHour(13.2);
	mike->getState();
	mike->setHour(16.2);
	mike->getState();
	//mike->m_taskfinished = true;
	mike->setHour(19.2);
	mike->getState();
	mike->m_taskfinished = true;
	mike->setHour(22.2);
	mike->getState();
	//mike->m_taskfinished = true;

	delete mike;

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

方寸间沧海桑田

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值