设计模式(行为模式)(状态模式)

Monster.h


#ifndef _MONSTER__
#define _MONSTER__

class MonsterStatus; //类前向声明

//怪物类
class Monster
{
public:
	Monster(int life);
	~Monster();

public:
	int GetLife() //获取怪物血量
	{
		return m_life;
	}
	void SetLife(int life) //设置怪物血量
	{
		m_life = life;
	}

	MonsterStatus* getCurrentState() //获取怪物当前状态
	{
		return m_pState;
	}
	void setCurrentState(MonsterStatus* pstate) //设置怪物当前状态
	{
		m_pState = pstate;
	}

public:
	void Attacked(int power); //怪物被攻击
	
private:
	int   m_life;   //血量(生命)
	MonsterStatus* m_pState; //持有状态对象
};

#endif

Monster.cpp



#include <iostream>
#include "Monster.h"
#include "MonsterStatus.h"

using namespace std;

//构造函数,怪物的初始状态从 “凶悍”开始
Monster::Monster(int life) :m_life(life)/*, m_pState(nullptr)*/
{
	//m_pState = new MonsterStatus_Feroc();
	m_pState = MonsterStatus_Feroc::getInstance();
}

Monster::~Monster()
{
	//delete m_pState;
}

//怪物被攻击
void Monster::Attacked(int power)
{
	m_pState->Attacked(power, this);
}

MonsterStatus.h


#ifndef _MONSTERSTATUS__
#define _MONSTERSTATUS__

class Monster; //类前向声明

//怪物状态类的父类
class MonsterStatus
{
public:
	virtual void Attacked(int power, Monster* mainobj) = 0;
	virtual ~MonsterStatus() {}
};

//凶悍状态类
class MonsterStatus_Feroc :public MonsterStatus
{
public:
	virtual void Attacked(int power, Monster* mainobj);
	//virtual void Attacked(int power, Monster* mainobj)
	//{
	//	std::cout << "怪物处于凶悍状态中,对主角进行疯狂反击!" <<std::endl;
	//	//......
	//}

public:
	static MonsterStatus_Feroc* getInstance()
	{
		static MonsterStatus_Feroc instance;
		return &instance;
	}
};

//不安状态类
class MonsterStatus_Worr :public MonsterStatus
{
public:
	virtual void Attacked(int power, Monster* mainobj);
	//virtual void Attacked(int power, Monster* mainobj)
	//{
	//	std::cout << "怪物处于不安状态中,对主角进行反击并呼唤支援!" << std::endl;
	//	//......
	//}
public:
	static MonsterStatus_Worr* getInstance()
	{
		static MonsterStatus_Worr instance;
		return &instance;
	}
};

//恐惧状态类
class MonsterStatus_Fear :public MonsterStatus
{
public:
	virtual void Attacked(int power, Monster* mainobj);
	//virtual void Attacked(int power, Monster* mainobj)
	//{
	//	std::cout << "怪物处于恐惧状态中,处于逃跑之中!" << std::endl;
	//	//......
	//}
public:
	static MonsterStatus_Fear* getInstance()
	{
		static MonsterStatus_Fear instance;
		return &instance;
	}
};

//死亡状态类
class MonsterStatus_Dead :public MonsterStatus
{
public:
	virtual void Attacked(int power, Monster* mainobj);
	//virtual void Attacked(int power, Monster* mainobj)
	//{
	//	std::cout << "怪物死亡!" << std::endl;
	//	//......
	//}
public:
	static MonsterStatus_Dead* getInstance()
	{
		static MonsterStatus_Dead instance;
		return &instance;
	}
};


#endif

MonsterStatus.cpp


#include <iostream>
#include "Monster.h"
#include "MonsterStatus.h"
using namespace std;

//各个状态子类的Attacked成员函数实现代码
void MonsterStatus_Feroc::Attacked(int power, Monster* mainobj)
{
	int orglife = mainobj->GetLife(); //暂存怪物血量用于后续比较
	if ((orglife - power) > 400) //怪物原来处于凶悍状态,现在 依然处于凶悍状态
	{
		//状态未变
		mainobj->SetLife(orglife - power); //怪物的剩余血量
		std::cout << "怪物处于凶悍状态中,对主角进行疯狂反击!" << std::endl;
		//.....处理其他动作逻辑比如反击
	}
	else
	{
		//不管下个状态是啥,总之不会是凶悍状态了,只可能是 不安,恐惧,死亡状态之一,先无条件的转到不安状态去(不安状态中会进行再次判断)
		/*delete mainobj->getCurrentState();
		mainobj->setCurrentState(new MonsterStatus_Worr);*/
		mainobj->setCurrentState(MonsterStatus_Worr::getInstance());
		mainobj->getCurrentState()->Attacked(power, mainobj);
	}
}

void MonsterStatus_Worr::Attacked(int power, Monster* mainobj)
{
	int orglife = mainobj->GetLife(); //暂存怪物血量用于后续比较
	if ((orglife - power) > 100) //怪物原来处于不安状态,现在 依然处于不安状态
	{
		//状态未变
		mainobj->SetLife(orglife - power); //怪物的剩余血量
		std::cout << "怪物处于不安状态中,对主角进行反击并呼唤支援!" << std::endl;
		//.....处理其他动作逻辑
	}
	else
	{
		//不管下个状态是啥,总之不会是凶悍、不安 状态了,只可能是 恐惧,死亡状态之一,先无条件的转到恐惧状态去
		/*delete mainobj->getCurrentState();
		mainobj->setCurrentState(new MonsterStatus_Fear);*/
		mainobj->setCurrentState(MonsterStatus_Fear::getInstance());
		mainobj->getCurrentState()->Attacked(power, mainobj);
	}
}

void MonsterStatus_Fear::Attacked(int power, Monster* mainobj)
{
	int orglife = mainobj->GetLife(); //暂存怪物血量用于后续比较
	if ((orglife - power) > 0) //怪物原来处于恐惧状态,现在 依然处于恐惧状态
	{
		//状态未变
		mainobj->SetLife(orglife - power); //怪物的剩余血量
		std::cout << "怪物处于恐惧状态中,处于逃跑之中!" << std::endl;
		//.....处理其他动作逻辑
	}
	else
	{
		//不管下个状态是啥,总之不会是凶悍、不安、恐惧 状态了,只可能是 死亡状态
		/*delete mainobj->getCurrentState();
		mainobj->setCurrentState(new MonsterStatus_Dead);*/
		mainobj->setCurrentState(MonsterStatus_Dead::getInstance());
		mainobj->getCurrentState()->Attacked(power, mainobj);
	}
}

void MonsterStatus_Dead::Attacked(int power, Monster* mainobj)
{
	int orglife = mainobj->GetLife();
	if (orglife > 0)
	{
		//还要把怪物生命值减掉
		mainobj->SetLife(orglife - power); 
		//....
	}
	cout << "怪物死亡!" << endl;
}

MyProject.cpp

// MyProject.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
//公众号:程序员速成 ,内含一辈子都让你感激自己的优质视频教程,欢迎关注

#include <iostream>
#include "Monster.h"

#ifdef _DEBUG   //只在Debug(调试)模式下
#ifndef DEBUG_NEW
#define DEBUG_NEW new(_NORMAL_BLOCK,__FILE__,__LINE__) //重新定义new运算符
#define new DEBUG_NEW
#endif
#endif

//#include <boost/type_index.hpp>
using namespace std;
//#pragma warning(disable : 4996) 

namespace _nmsp1
{
	/*
	//怪物状态枚举值
	enum MonsterState
	{
		MonS_Fer,   //凶悍
		MonS_Worr,  //不安
		MonS_Fear,  //恐惧
		MonS_Dead   //死亡
	};

	//怪物类
	class Monster
	{
	public:
		//构造函数,怪物的初始状态从 凶悍 开始
		Monster(int life) :m_life(life), m_status(MonS_Fer) {}

	public:
		void Attacked(int power) //怪物被攻击,power表示主角对怪物的攻击力(怪物丢失的血量)
		{
			m_life -= power; //怪物剩余的血量
			if (m_status == MonS_Fer) //凶悍
			{
				if (m_life > 400)
				{
					cout << "怪物受到" << power << "点伤害并对主角进行疯狂的反击!" << endl;
					//处理其他动作逻辑
				}
				else if (m_life > 100)
				{
					cout << "怪物受到" << power << "点伤害并对主角进行反击,怪物变得焦躁不安并开始呼唤支援!" << endl;
					m_status = MonS_Worr;
					//处理其他动作逻辑
				}
				else if (m_life > 0)
				{
					cout << "怪物受到" << power << "点伤害,怪物变得恐惧并开始逃跑!" << endl;
					m_status = MonS_Fear;
					//处理其他动作逻辑
				}
				else
				{
					cout << "怪物受到" << power << "点伤害,已经死亡!" << endl;
					m_status = MonS_Dead;
					//处理其他动作逻辑
				}
			}
			else if (m_status == MonS_Worr) //不安 ,血量 <= 400,> 100
			{
				if (m_life > 100)
				{
					cout << "怪物受到" << power << "点伤害并对主角进行反击,并继续急促的呼唤支援!" << endl;					
					//处理其他动作逻辑
				}
				else if (m_life > 0)
				{
					cout << "怪物受到" << power << "点伤害,怪物变得恐惧并开始逃跑!" << endl;
					m_status = MonS_Fear;
					//处理其他动作逻辑
				}
				else
				{
					cout << "怪物受到" << power << "点伤害,已经死亡!" << endl;
					m_status = MonS_Dead;
					//处理其他动作逻辑
				}
			}
			else if (m_status == MonS_Fear) //恐惧
			{
				if (m_life > 0)
				{
					cout << "怪物受到" << power << "点伤害,怪物继续逃跑!" << endl;					
					//处理其他动作逻辑
				}
				else
				{
					cout << "怪物受到" << power << "点伤害,已经死亡!" << endl;
					m_status = MonS_Dead;
					//处理其他动作逻辑
				}
			}
			else  //怪物已经处于死亡状态
			{
				cout << "怪物已死亡,不能再被攻击!" << endl;
			}
		}

	private:
		int   m_life;   //血量(生命)
		MonsterState m_status; //初始状态
	};
	*/
}

int main()
{
	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);//程序退出时检测内存泄漏并显示到“输出”窗口
	
	//状态(State)模式:行为型,有限状态机
	//状态模式的突出特点:用类来表示状态——策略模式(用类来表示策略)
	//(1)一个基本的状态转换范例
	//有限状态机(Finite State Mache,所写:FSM),简称状态机。
	  //当某个事件(转移条件)发生时,会根据当前状态决定你执行哪种动作,然后进入下一种状态。
	//约定:怪物生命 500。
	  //a) 怪物血量 > 400 ,怪物->凶悍,反击
	  //b) 怪物血量 <= 400, > 100,怪物->不安,反击并呼唤附近其他怪物支援
	  //c) 怪物血量 <= 100,怪物->恐惧,逃跑
	  //d) 怪物血量 <= 0,怪物->死亡,不能再被主角攻击
	//状态类的存在价值:使业务逻辑代码更加清晰和易于维护。

	//(2)引入状态(Status)模式
	//定义:允许一个对象(怪物)在其内部状态改变(比如从凶悍状态改变为不安状态)时改变它的行为(比如从疯狂反击变为反击并互换支援),
	  //对象看起来似乎修改了它的类。
	//UML图中的三种角色
	//a)Context(环境类):指Monster类。
	//b)State(抽象状态类):指MonsterStatus子类。
	//c)ConcreteState(具体状态类):指MonsterStatus_Feroc、MonsterStatus_Worr、MonsterStatus_Fear、MonsterStatus_Dead

	//如下两种情况下,可以考虑使用状态模式:
	//a)对象行为取决于其状态,该对象需要根据其状态来改变行为。
	//b)一个操作中含有庞大的条件分支语句,而这些分支语句的执行依赖于对象的当前状态。

	//当项目中某对象的状态特别时,考虑 查表法——对象状态转换

	/*
	_nmsp1::Monster monster(500);
	cout << "怪物出生,当前处于凶悍状态,500点血!" << endl;
	monster.Attacked(20);
	monster.Attacked(100);
	monster.Attacked(200);
	monster.Attacked(170);
	monster.Attacked(100);
	monster.Attacked(100);
	*/
	
	Monster monster(500);
	cout << "怪物出生,当前处于凶悍状态,500点血!" << endl;
	monster.Attacked(20);
	monster.Attacked(100);
	monster.Attacked(200);
	monster.Attacked(170);
	monster.Attacked(100);
	monster.Attacked(100);
	return 0;
}

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

lz_煜

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

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

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

打赏作者

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

抵扣说明:

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

余额充值