栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【学习笔记】C++下的状态模式(程杰-大话设计模式)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【学习笔记】C++下的状态模式(程杰-大话设计模式)

引入:小菜一天的工作状态,上午状态好,效率高。中午犯困想睡觉,下午逐渐恢复精神,开始疯狂赶进度。 这就是状态跟随时间的变化。


一、工作状态变化-函数版

main.cpp

#include

using namespace std;

static int Hour = 0; // 时间
static bool	WorkFinished = false; // 任务完成标记

static void WriteProgrtam()
{
	if (Hour < 12 && Hour >= 8)
	{
		cout << "当前时间: " << Hour << ",上午工作,精神百倍。" << endl;
	}
	else if (Hour >= 12 && Hour < 13)
	{
		cout << "当前时间: " << Hour << ",又饿又困,需要午休。" << endl;
	}
	else if (Hour >= 13 && Hour < 17)
	{
		cout << "当前时间: " << Hour << ",下午状态不错,继续努力。" << endl;
	}
	else
	{
		if (WorkFinished)
		{
			cout << "当前时间: " << Hour << ", 任务完成,下班回家!" << endl;
		}
		else
		{
			if (Hour < 21)
			{
				cout << "当前时间: " << Hour << ",加班吧,疲劳至极。" << endl;
			}
			else
			{
				cout << "当前时间: " << Hour << ",不行了,睡觉。" << endl;
			}
		}
	}
}

int main()
{
	Hour = 9;
	WriteProgrtam();
	Hour = 10;
	WriteProgrtam();
	Hour = 11;
	WriteProgrtam();
	Hour = 12;
	WriteProgrtam();
	Hour = 13;
	WriteProgrtam();
	Hour = 14;
	WriteProgrtam();
	Hour = 17;
	WriteProgrtam();

	WorkFinished = true;
	WriteProgrtam();


	WorkFinished = false;
	Hour = 19;
	WriteProgrtam();
	Hour = 22;
	WriteProgrtam();

	system("pause");

	return 0;
}

运行结果: 

很粗糙的实现,根本不是面向对象编程的思想。

二、工作状态-分类版

设置一个工作类,其中Hour以及workFinished是该类的属性。writePrograme是该类的一个方法。

Work.h

#pragma once
#include

using namespace std;

class Work
{
private:
	int Hour = 0;
	bool WorkFinished = false;
public:
	void writeProgram();
	void setHour(int Hour);
	int getHour();
	void setWorkFinished(bool WorkFinished);
	bool getWorkFinished();
};

Work.cpp

#include "Work.h"

void Work::writeProgram()
{
	if (this->Hour < 12 && this->Hour >= 8)
	{
		cout << "当前时间: " << this->Hour << ",上午工作,精神百倍。" << endl;
	}
	else if (this->Hour >= 12 && this->Hour < 13)
	{
		cout << "当前时间: " << this->Hour << ",又饿又困,需要午休。" << endl;
	}
	else if (this->Hour >= 13 && this->Hour < 17)
	{
		cout << "当前时间: " << this->Hour << ",下午状态不错,继续努力。" << endl;
	}
	else
	{
		if (WorkFinished)
		{
			cout << "当前时间: " << this->Hour << ", 任务完成,下班回家!" << endl;
		}
		else
		{
			if (this->Hour < 21)
			{
				cout << "当前时间: " << this->Hour << ",加班吧,疲劳至极。" << endl;
			}
			else
			{
				cout << "当前时间: " << this->Hour << ",不行了,睡觉。" << endl;
			}
		}
	}
}

void Work::setHour(int Hour)
{
	this->Hour = Hour;
}

int Work::getHour()
{
	return this->Hour;
}

void Work::setWorkFinished(bool WorkFinished)
{
	this->WorkFinished = WorkFinished;
}

bool Work::getWorkFinished()
{
	return this->WorkFinished;
}

客户端:

#include
#include"Work.h"

void test01()
{
	// emergency project
	Work* emergencyProjects = new Work();
	emergencyProjects->setHour(9);
	emergencyProjects->writeProgram();
	emergencyProjects->setHour(10);
	emergencyProjects->writeProgram();
	emergencyProjects->setHour(12);
	emergencyProjects->writeProgram();
	emergencyProjects->setHour(13);
	emergencyProjects->writeProgram();
	emergencyProjects->setHour(14);
	emergencyProjects->writeProgram();
	emergencyProjects->setHour(17);
	emergencyProjects->writeProgram();

	emergencyProjects->setWorkFinished(false);
	emergencyProjects->writeProgram();
	emergencyProjects->setHour(19);
	emergencyProjects->writeProgram();
	emergencyProjects->setHour(22);
	emergencyProjects->writeProgram();

	cout << "-------------------------------" << endl;
	cout << endl;

	emergencyProjects->setWorkFinished(true);
	emergencyProjects->setHour(17);
	emergencyProjects->writeProgram();
	emergencyProjects->setHour(19);
	emergencyProjects->writeProgram();
	emergencyProjects->setHour(22);
	emergencyProjects->writeProgram();

	emergencyProjects = NULL;
	delete emergencyProjects;
}

int main()
{
	test01();
	system("pause");
	return 0;
}

运行结果:

 存在的问题:

Work类的writeProgram()方法是一个“Long Method”,也就是说这个方法过长。

同时该方法内保护大量的if-else判断分支,意味着它的责任过大。

而面向对象设计希望做到代码责任分解,即做到“单一职责原则”。

目前的writeProgram()如果需要修改,修改代价、难度大。

三、状态模式(State Pattern)

状态模式(State),当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变其类。

本质:解决当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。

 状态模式的有点:将于特定状态相关的行为局部化,并且将不同状态的行为分割开来。

 使用状态模式的时机:如果某个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它自身的行为,就可以考虑使用状态模式。

四、工作状态-状态模式版

 State.h 抽象状态类

#pragma once
#include
#include"Work.h"

using namespace std;

// 抽象状态类
class State
{
public:
	virtual void WriteProgram(Work* w) = 0;
};

Work.h

#pragma once
#include
// #include"State.h"
// #include"ForenoonState.h"
using namespace std;

class State;

class Work
{
private:
	State* current;
	double hour;
	bool finish = false;
public:
	Work();
	void setHour(double hour);
	double getHour();

	void setWorkFinished(bool finish);
	bool getWorkFinished();

	void setState(State* s);

	void WriteProgram();

};

Work.cpp

#include "Work.h"
#include "ForenoonState.h"

Work::Work()
{
	// 初始化状态为上午工作状态
	current = new ForenoonState;
}

void Work::setHour(double hour)
{
	this->hour = hour;
}

double Work::getHour()
{
	return this->hour;
}

void Work::setWorkFinished(bool finish)
{
	this->finish = finish;
}

bool Work::getWorkFinished()
{
	return this->finish;
}

void Work::setState(State* s)
{
	current = s;
}

void Work::WriteProgram()
{
	current->WriteProgram(this);
}

【Mark】问题记录:

在编译项目时遇到了 error C2504: “State” 未定义基类的问题

针对这个问题,我参考了这篇博客,启发很大:

error C2504: 未定义基类_wklnewlife的博客-CSDN博客_c++ 未定义基类

原因就是我在main文件中头文件的编译顺序是首先编译State.h,State.h中由要引入Work.h,然而Work.h中又包含了State.h的头文件。因此变成了一个闭环。导致无法编译而报错。

此外,我Work.h中需要使用ForenoonState类来初始化我的Work构造函数。但是,ForenoonStatge.h还是需要引入State.h文件,怎么办?

在Work.cpp文件中引入ForenoonState.h即可。

ForenoonState.h 上午工作状态类

#pragma once
#include
#include"State.h"
#include
#include"NoonState.h"

using namespace std;

class ForenoonState : public State
{
public:
	void WriteProgram(Work* w);
};

ForenoonState.cpp

#include "ForenoonState.h"

void ForenoonState::WriteProgram(Work* w)
{
	if (w->getHour() < 12)
	{
		cout << "当前时间:" + to_string(w->getHour()) << "点,上午工作,精神百倍!" << endl;
	}
	else
	{
		w->setState(new NoonState);
		w->WriteProgram();
	}
}

NoonState.h 中午工作状态类

#pragma once
#include
#include
#include"State.h"
#include"ForenoonState.h"
#include"AfternoonState.h"

using namespace std;

class NoonState : public State
{
public:
	void WriteProgram(Work* w);
};

NoonState.cpp 

#include "NoonState.h"

void NoonState::WriteProgram(Work* w)
{
	if (w->getHour() < 13)
	{
		cout << "当前时间:" + to_string(w->getHour()) << "点,饿了,吃午饭;犯困,午休。" << endl;
	}
	else
	{
		w->setState(new AfternoonState);
		w->WriteProgram();
	}
}

AternoonState.h 下午工作状态类

#pragma once
#include
#include
#include"State.h"
#include"EveningState.h"

using namespace std;

class AfternoonState : public State
{
public:
	void WriteProgram(Work* w);
};

AternoonState.cpp

#include "AfternoonState.h"

void AfternoonState::WriteProgram(Work* w)
{
	if (w->getHour() < 17)
	{
		cout << "当前时间:" + to_string(w->getHour()) << "点,下午状态还不错,继续努力。" << endl;
	}
	else
	{
		w->setState(new EveningState);
		w->WriteProgram();
	}
}

EveningState.h 晚上的工作状态类

#pragma once
#include
#include
#include"State.h"
#include"SleepingState.h"
#include"RestState.h"

using namespace std;

class EveningState :public State
{
public:
	void WriteProgram(Work* w);
};

EveningState.cpp

#include "EveningState.h"

void EveningState::WriteProgram(Work* w)
{
	if (w->getWorkFinished())
	{
		w->setState(new RestState);
		w->WriteProgram();
	}
	else
	{
		if (w->getHour() < 21)
		{
			cout << "当前时间:" + to_string(w->getHour()) << "点,加班哦,疲累至极。" << endl;
		}
		else
		{
			w->setState(new SleepingState);
			w->WriteProgram();
		}
	}

}

RestState.h 休息状态类

#pragma once
#include
#include
#include"State.h"

using namespace std;

class RestState : public State
{
public:
	void WriteProgram(Work* w);
};

RestState.cpp

#include "RestState.h"

void RestState::WriteProgram(Work* w)
{
	cout << "当前时间:" + to_string(w->getHour()) << "点,下班回家了。" << endl;
}

SleepingState.h 睡觉状态类

#pragma once
#include
#include
#include"State.h"

using namespace std;

class SleepingState : public State
{
public:
	void WriteProgram(Work* w);
};

SleepingState.cpp 

#include "SleepingState.h"

void SleepingState::WriteProgram(Work* w)
{
	cout << "当前时间:" + to_string(w->getHour()) << "点,不行了,睡着了。" << endl;
}

客户端(完全一样):

#pragma once
#include
#include"State.h"
#include"ForenoonState.h"
#include"NoonState.h"
#include"AfternoonState.h"
#include"EveningState.h"
#include"SleepingState.h"
#include"RestState.h"

void test01()
{
	Work* emergencyProjects = new Work();
	emergencyProjects->setHour(9);
	emergencyProjects->WriteProgram();
	emergencyProjects->setHour(10);
	emergencyProjects->WriteProgram();
	emergencyProjects->setHour(12);
	emergencyProjects->WriteProgram();
	emergencyProjects->setHour(13);
	emergencyProjects->WriteProgram();
	emergencyProjects->setHour(14);
	emergencyProjects->WriteProgram();
	emergencyProjects->setHour(17);
	emergencyProjects->WriteProgram();

	emergencyProjects->setWorkFinished(true);
	emergencyProjects->WriteProgram();
	emergencyProjects->setHour(19);
	emergencyProjects->WriteProgram();
	emergencyProjects->setHour(22);
	emergencyProjects->WriteProgram();
	cout << endl;
	cout << "---------------------" << endl;
	cout << endl;
	emergencyProjects->setWorkFinished(false);
	emergencyProjects->WriteProgram();
	emergencyProjects->setHour(19);
	emergencyProjects->WriteProgram();
	emergencyProjects->setHour(22);
	emergencyProjects->WriteProgram();

	emergencyProjects = NULL;
	delete emergencyProjects;
}

int main()
{

	test01();

	system("pause");

	return 0;
}

运行结果:

 

 现在,增加一个需求,老板要求20点之后必须回家。

在状态模式下很好修改,增加一个ForceToLeave状态类,同样继承自State这个抽象状态。

ForceToLerave.h

#pragma once
#include
#include
#include"State.h"

class ForceToLeave : public State
{
public:
	void WriteProgram(Work* w);
};

ForceToLerave.cpp

#include "ForceToLeaveState.h"

void ForceToLeave::WriteProgram(Work * w)
{
	cout << "当前时间:" + to_string(w->getHour()) << "点,不许内卷,赶快回家!" << endl;
}

在晚上工作状态类进行逻辑修改:

#include "EveningState.h"

void EveningState::WriteProgram(Work* w)
{
	if (w->getWorkFinished())
	{
		w->setState(new RestState);
		w->WriteProgram();
	}
	else
	{
		if (w->getHour() < 20 && w->getHour() >= 17)
		{
			cout << "当前时间:" + to_string(w->getHour()) << "点,加班哦,疲累至极。" << endl;
		}
		else if (w->getHour() >= 20 && w->getHour() < 22)
		{
			w->setState(new ForceToLeave);
			w->WriteProgram();
		}
		else
		{
			w->setState(new SleepingState);
			w->WriteProgram();
		}
	}

}

 运行结果:

 参考资料:《大话设计模式》,作者:程杰

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/883507.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号