引入:小菜一天的工作状态,上午状态好,效率高。中午犯困想睡觉,下午逐渐恢复精神,开始疯狂赶进度。 这就是状态跟随时间的变化。
一、工作状态变化-函数版
main.cpp
#includeusing 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 #includeusing 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();
}
}
}
运行结果:
参考资料:《大话设计模式》,作者:程杰



