第16章状态模式

一 概念

  • 状态模式,当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
  • 状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况,把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑化。

二 UML图

  • State 抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为。
  • Context类,维护一个ConcreteState子类的实例,这个实例定义当前的状态。
  • ConcreteState类,具体状态,每一个子类实现一个与Context的一个状态相关的行为。

三 状态模式好处与用处

  • 将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。
  • 将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个ConcreteState中,所以通过定义新的子类可以很容易的增加新的状态和转换。
  • 状态模式通过把各种状态转移逻辑分布到State的子类之间,来减少相互间的依赖。

四 什么时候应该考虑使用状态模式?

  • 当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式。

五 C++代码实现
lesson1.h

#pragma once
#include <iostream>
using namespace std;

class Work;

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

class Work
{
public:
	Work();
	void SetHour(int hour);
	int GetHour();
	void SetTaskFinished(bool finish);
	bool GetTaskFinished();
	void SetState(State* s);
	void WriteProgram();
private:
	bool m_finish;
	int m_hour;
	State* current;
};


//上午和中午工作状态类
class ForenoonState : public State
{
public:
	void WriteProgram(Work* w) override;
};
//中午的工作状态
class NoonState : public State
{
public:
	void WriteProgram(Work* w) override;
};
//下午工作状态
class AfternoonState : public State
{
public:
	void WriteProgram(Work* w) override;
};
//晚间工作状态
class EveningState : public State
{
public:
	void WriteProgram(Work* w) override;
};
//睡眠状态
class SleepingState : public State
{
public:
	void WriteProgram(Work* w) override;
};
//下班休息状态
class RestState : public State
{
public:
	void WriteProgram(Work* w) override;
};

lesson1.cpp

#include "pch.h"
#include "lesson1.h"
#include <iostream>
using namespace std;

class Work;


Work::Work()
{
	this->m_finish = false;
	this->current = new ForenoonState();
}
void Work::SetHour(int hour)
{
	this->m_hour = hour;
}
int Work::GetHour() 
{
	return this->m_hour;
}
void Work::SetTaskFinished(bool finish)
{
	this->m_finish = finish;
}
bool Work::GetTaskFinished() 
{
	return this->m_finish;
}
void Work::SetState(State* s)
{
	current = s;
}
void Work::WriteProgram()
{
	current->WriteProgram(this);
}


//上午和中午工作状态类

void ForenoonState::WriteProgram(Work* w)
{
	if (w->GetHour() < 12)
	{
		cout << "当前时间: " << w->GetHour() << "点,上午工作,精神百倍" << endl;
	}
	else
	{
		//超过12点 则转入中午工作状态
		w->SetState(new NoonState);
		w->WriteProgram();
	}
}

//中午的工作状态
void NoonState::WriteProgram(Work* w)
{
	if (w->GetHour() < 13)
	{
		cout << "当前时间: " << w->GetHour() << "点,饿了,午饭;犯困,午休" << endl;
	}
	else
	{
		//超过13点 则转入中午工作状态
		w->SetState(new AfternoonState);
		w->WriteProgram();
	}
}

//下午工作状态
void  AfternoonState::WriteProgram(Work* w) 
{
	if (w->GetHour() < 17)
	{
		cout << "当前时间: " << w->GetHour() << "点,下午状态还不错,继续努力" << endl;
	}
	else
	{
		//超过13点 则转入中午工作状态
		w->SetState(new EveningState);
		w->WriteProgram();
	}
}

//晚间工作状态

void EveningState::WriteProgram(Work* w) 
{
	if (w->GetTaskFinished())
	{
		//如果完成任务,则转入下班状态
		w->SetState(new RestState);
		w->WriteProgram();
	}
	else
	{
		if (w->GetHour() < 21)
		{
			cout << "当前时间: " << w->GetHour() << "点,加班哦,疲累之极" << endl;
		}
		else
		{
			//超过21点 则转入中午工作状态
			w->SetState(new SleepingState);
			w->WriteProgram();
		}
	}
}

//睡眠状态

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

//下班休息状态

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

main.cpp

// lesson1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include <iostream>
#include "lesson1.h"
using namespace std;

int main()
{
	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->SetTaskFinished(true);
	emergencyProjects->WriteProgram();
	emergencyProjects->SetHour(19);
	emergencyProjects->WriteProgram();
	emergencyProjects->SetHour(22);
	emergencyProjects->WriteProgram();
	return 0;
}

原文地址:https://www.cnblogs.com/Manual-Linux/p/11161576.html