大话设计模式C++实现-第16章-状态模式

一、UML图



二、概念

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


三、说明

下面是来自书本和网络的对状态模式的定义和分析:

(1)状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。看起来,状态模式好像是神通广大很厉害似的——居然能够修改自身的类

(2)适用场景

a)状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判 断逻辑简单化。(简单来说,就是把各种if else 转变成了一个个的具体状态,原来if else 每种情况下的操作现在转换到了某个具体状态中)

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


四、角色

(1)Context类:在该类内部维护一个ConcreteState子类的一个实例,这个实例定义当前的状态。

(2)State类:抽象状态类,定义一个 接口以封装与Context的一个特定状态相关的行为。

(3)ConcreteStateA,ConcreteStateB类:具体状态类,每一个子 类实现一个与Context的一个状态相关的行为。


五、C++实现

(1)State.h(抽象状态类和具体状态类的声明和定义都在State.h和State.cpp中)

#ifndef STATE
#define STATE

//#include "Work.h"
extern class Work;

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

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

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

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

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

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

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

#endif


(2)State.cpp

#include <iostream>
#include "State.h"
#include "Work.h"

using namespace std;

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

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

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

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

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

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

(3)Work.h(这里的Work就是状态模式中的Context)

#ifndef WORK
#define WORK

#include "State.h"

class Work
{
private:
	State* current;

	double Hour;
	bool finish;

public:
	Work();
	~Work();
	
	double getHour();
	void setHour(double HOUR);
	
	bool getFinish();
	void setFinish(bool FINISH);

	void setState(State* s);

	void writeProgram();
};

#endif

(4)Work.cpp

#include "Work.h"

Work::Work()
{
	current=new ForenoonState;
	Hour=9;
	finish=false;
}

Work::~Work()
{
	if(current!=0)
		delete current;
}

double Work::getHour()
{
	return Hour;
}
void Work::setHour(double HOUR)
{
	Hour=HOUR;
}

bool Work::getFinish()
{
	return finish;
}
void Work::setFinish(bool FINISH)
{
	finish=FINISH;
}

void Work::setState(State* s)
{
	if(current!=0)
		delete current;

	current=s;
}

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

(5)main.cpp(客户端)

#include <iostream>
#include <cstdlib>
#include "Work.h"
//#include "State.h"

using namespace std;

void main()
{
	Work emergencyProjects;

	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.setFinish(false);

	emergencyProjects.setHour(19);
	emergencyProjects.writeProgram();

	emergencyProjects.setHour(22);
	emergencyProjects.writeProgram();

	system("pause");
}

注意:上面的代码会出现两个类相互调用的情况,请查看日志:C++中两个类互相引用的解决方法

(6)运行截图


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值