ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

《C++新经典设计模式》之第12章 状态模式

2026/9/13 16:08:06 拓冰建站 浏览量
《C++新经典设计模式》之第12章 状态模式

《C++新经典设计模式》之第12章 状态模式

        • 状态模式.cpp

状态模式.cpp
#include <iostream>
#include <memory>
using namespace std;// 用类表示状态, 一般用于有限状态机
// 状态机3部分组成:状态(State)、事件(Event)、动作(Action)
// 事件(转移条件, 触发状态变化的行为或动作)发生时, 状态改变, 可能执行动作// 允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类
// 3种角色
// Context(环境/上下文类),该类对象拥有多种状态以便对这些状态进行维护
// State(抽象状态类),定义接口以封装与环境类的特征状态相关的行为,声明不同状态对应的方法
// ConcreteState(具体状态类),实现与环境类该状态相关的行为namespace ns1
{class Monster // 怪物类{public:enum MonsterState // 怪物状态枚举值{MonS_Fer,  // 凶悍MonS_Worr, // 不安MonS_Fear, // 恐惧MonS_Dead  // 死亡};private:int m_life;            // 血量(生命值)MonsterState m_status; // 初始状态public:Monster(int life, MonsterState status = MonS_Fer) : m_life(life), m_status(status) {}public:void Attacked(int power) // 怪物被攻击。参数power表示主角对怪物的攻击力(即怪物丢失的血量){m_life -= power; // 怪物剩余的血量switch (m_status){case MonS_Fer:if (m_life > 400){cout << "monster " << power << " hurt, attact!" << endl;// 处理其他动作逻辑比如反击}else if (m_life > 100){cout << "monster " << power << " hurt, attact, help!" << endl;m_status = MonS_Worr;// 处理其他动作逻辑比如反击和呼唤支援}else if (m_life > 0){cout << "monster " << power << " hurt, MonS_Fear, run!" << endl;m_status = MonS_Fear;// 处理其他动作逻辑比如逃跑}else{cout << "monster " << power << " hurt, dead!" << endl;m_status = MonS_Dead;// 处理怪物死亡后事宜比如怪物尸体定时消失等}break;case MonS_Worr: // 目前怪物已经处于不安状态, 这说明怪物的血量<=400并且>100if (m_life > 100){cout << "monster " << power << " hurt, attact, help!" << endl;// 处理其他动作逻辑比如反击和呼唤支援}else if (m_life > 0){cout << "monster " << power << " hurt, MonS_Fear, run!" << endl;m_status = MonS_Fear;// 处理其他动作逻辑比如逃跑}else{cout << "monster " << power << " hurt, dead!" << endl;m_status = MonS_Dead;// 处理怪物死亡后事宜比如怪物尸体定时消失等}break;case MonS_Fear:if (m_life > 0){cout << "monster " << power << " hurt, run!" << endl;// 处理其他动作逻辑比如逃跑}else{cout << "monster " << power << " hurt, dead!" << endl;m_status = MonS_Dead;// 处理怪物死亡后事宜比如怪物尸体定时消失等}break;default: // 怪物已经处于死亡状态cout << "monster dead, cannot be attacketed!" << endl;break;}}};
}namespace ns2
{class Monster;      // 类前向声明class MonsterStatus // 怪物状态类{public:virtual ~MonsterStatus() {}virtual void Attacked(int power, Monster *const mainobj) = 0;};class MonsterStatus_Feroc : public MonsterStatus // 凶悍状态类{public:// 传递进来的参数是否有必要使用, 开发者自行斟酌void Attacked(int power, Monster *const mainobj) override{cout << "MonsterStatus_Feroc, attackt!" << endl;// 处理其他动作逻辑比如反击}};class MonsterStatus_Worr : public MonsterStatus // 不安状态类{public:void Attacked(int power, Monster *const mainobj) override{cout << "MonsterStatus_Worr, attackt, help!" << endl;// 处理其他动作逻辑比如反击和不停的呼唤支援}};class MonsterStatus_Fear : public MonsterStatus // 恐惧状态类{public:void Attacked(int power, Monster *const mainobj) override{cout << "MonsterStatus_Fear, run!" << endl;// 处理其他动作逻辑比如逃跑}};class MonsterStatus_Dead : public MonsterStatus // 死亡状态类{public:void Attacked(int power, Monster *const mainobj) override{cout << "dead!" << endl;// 处理怪物死亡后事宜比如怪物尸体定时消失等}};class Monster // 怪物类{int m_life;                         // 血量(生命值)shared_ptr<MonsterStatus> m_pState; // 持有状态对象public:Monster(int life, const shared_ptr<MonsterStatus> &pState = make_shared<MonsterStatus_Feroc>()) : m_life(life), m_pState(pState) {}public:void Attacked(int power){int orglife = m_life; // 暂存原来的怪物血量值用于后续比较m_life -= power;      // 怪物剩余的血量if (orglife > 400)    // 怪物原来处于凶悍状态{if (m_life > 400) // 状态未变{// cout << "monster " << power << "点伤害并对主角进行疯狂的反击!" << endl;m_pState->Attacked(power, this); // 其他的逻辑代码被本Monster类委托给了具体状态类来处理}else if (m_life > 100) // 状态从凶悍改变到不安{// cout << "monster " << power << "点伤害并对主角进行反击, 怪物变得焦躁不安并开始呼唤支援!" << endl;m_pState.reset(new MonsterStatus_Worr()); // 怪物转到不安状态m_pState->Attacked(power, this);}else if (m_life > 0) // 状态从凶悍状态改变到恐惧状态, 主角的攻击太恐怖了{// cout << "monster " << power << "点伤害, 怪物变得恐惧并开始逃跑!" << endl;m_pState.reset(new MonsterStatus_Fear()); // 怪物转到恐惧状态m_pState->Attacked(power, this);}else // 状态从凶悍改变到死亡{// cout << "monster " << power << "点伤害, 已经死亡!" << endl;m_pState.reset(new MonsterStatus_Dead()); // 怪物转到死亡状态m_pState->Attacked(power, this);}}else if (orglife > 100) // 怪物原来处于不安状态{if (m_life > 100) // 状态未变{// cout << "monster " << power << "点伤害并对主角进行反击, 并继续急促的呼唤支援!" << endl;m_pState->Attacked(power, this);}else if (m_life > 0) // 状态从不安改变到恐惧{// cout << "monster " << power << "点伤害, 怪物变得恐惧并开始逃跑!" << endl;m_pState.reset(new MonsterStatus_Fear()); // 怪物转到恐惧状态m_pState->Attacked(power, this);}else // 状态从不安改变到死亡{// cout << "monster " << power << "点伤害, 已经死亡!" << endl;m_pState.reset(new MonsterStatus_Dead()); // 怪物转到死亡状态m_pState->Attacked(power, this);}}else if (orglife > 0) // 怪物原来处于恐惧状态{if (m_life > 0) // 状态未变{// cout << "monster " << power << "点伤害, 怪物继续逃跑!" << endl;m_pState->Attacked(power, this);}else // 状态从恐惧改变到死亡{// cout << "monster " << power << "点伤害, 已经死亡!" << endl;m_pState.reset(new MonsterStatus_Dead()); // 怪物转到死亡状态m_pState->Attacked(power, this);}}else // 怪物已经死亡{// 已经死亡的怪物, 状态不会继续发生改变//  cout << "怪物已死亡, 不能再被攻击!" << endl;m_pState->Attacked(power, this);}}};
}namespace ns3
{class Monster;      // 类前向声明class MonsterStatus // 怪物状态类{public:virtual ~MonsterStatus() {}virtual void Attacked(int power, Monster *const mainobj) = 0;};class MonsterStatus_Feroc : public MonsterStatus{public:void Attacked(int power, Monster *const mainobj) override;};class MonsterStatus_Worr : public MonsterStatus{public:void Attacked(int power, Monster *const mainobj) override;};class MonsterStatus_Fear : public MonsterStatus{public:void Attacked(int power, Monster *const mainobj) override;};class MonsterStatus_Dead : public MonsterStatus{public:void Attacked(int power, Monster *const mainobj) override;};class Monster // 怪物类定义{int m_life;                         // 血量(生命值)shared_ptr<MonsterStatus> m_pState; // 持有状态对象public:Monster(int life, const shared_ptr<MonsterStatus> &pState = make_shared<MonsterStatus_Feroc>()) : m_life(life), m_pState(pState) {}public:void Attacked(int power) { m_pState->Attacked(power, this); } // 怪物被攻击public:int GetLife() const { return m_life; }                                               // 获取怪物血量void SetLife(int life) { m_life = life; }                                            // 设置怪物血量shared_ptr<MonsterStatus> getCurrentState() const { return m_pState; }               // 获取怪物当前状态void setCurrentState(const shared_ptr<MonsterStatus> &pState) { m_pState = pState; } // 设置怪物当前状态};void MonsterStatus_Feroc::Attacked(int power, Monster *const mainobj) // 凶悍状态类{int orglife = mainobj->GetLife(); // 暂存原来的怪物血量值用于后续比较if ((orglife - power) > 400)      // 怪物原来处于凶悍状态, 现在依旧处于凶悍状态{// 状态未变mainobj->SetLife(orglife - power); // 怪物剩余的血量cout << "MonsterStatus_Feroc, attackt!" << endl;// 处理其他动作逻辑比如反击}else{// 不管下个状态是啥, 总之不会是凶悍状态, 只可能是不安、恐惧、死亡状态之一, 先无条件转到不安状态去(不安状态中会进行再次判断)mainobj->setCurrentState(make_shared<MonsterStatus_Worr>());// mainobj->getCurrentState()->Attacked(power, mainobj);mainobj->Attacked(power);}}void MonsterStatus_Worr::Attacked(int power, Monster *const mainobj) // 不安状态类{int orglife = mainobj->GetLife();if ((orglife - power) > 100) // 怪物原来处于不安状态, 现在依旧处于不安状态{// 状态未变mainobj->SetLife(orglife - power); // 怪物剩余的血量cout << "MonsterStatus_Worr, attackt, help!" << endl;// 处理其他动作逻辑比如反击和不停的呼唤支援}else{// 不管下个状态是啥, 总之不会是凶悍和不安状态, 只可能是恐惧、死亡状态之一, 先无条件转到恐惧状态去mainobj->setCurrentState(make_shared<MonsterStatus_Fear>());// mainobj->getCurrentState()->Attacked(power, mainobj);mainobj->Attacked(power);}}void MonsterStatus_Fear::Attacked(int power, Monster *const mainobj) // 恐惧状态类{int orglife = mainobj->GetLife();if ((orglife - power) > 0) // 怪物原来处于恐惧状态, 现在依旧处于恐惧状态{// 状态未变mainobj->SetLife(orglife - power); // 怪物剩余的血量cout << "MonsterStatus_Fear, run!" << endl;// 处理其他动作逻辑比如逃跑}else{// 不管下个状态是啥, 总之不会是凶悍、不安和恐惧状态, 只可能是死亡状态mainobj->setCurrentState(make_shared<MonsterStatus_Dead>());// mainobj->getCurrentState()->Attacked(power, mainobj);mainobj->Attacked(power);}}void MonsterStatus_Dead::Attacked(int power, Monster *const mainobj) // 死亡状态类{int orglife = mainobj->GetLife();if (orglife > 0){// 还要把怪物生命值减掉mainobj->SetLife(orglife - power); // 怪物剩余的血量// 处理怪物死亡后事宜比如怪物尸体定时消失等}cout << "dead!" << endl;}
}namespace ns4
{class Monster;      // 类前向声明class MonsterStatus // 怪物状态类{public:virtual ~MonsterStatus() {}virtual void Attacked(int power, Monster *const mainobj) = 0;};class MonsterStatus_Feroc : public MonsterStatus{public:void Attacked(int power, Monster *const mainobj) override;public:static shared_ptr<MonsterStatus> getInstance(){static shared_ptr<MonsterStatus> instance(new MonsterStatus_Feroc());return instance;}};class MonsterStatus_Worr : public MonsterStatus{public:void Attacked(int power, Monster *const mainobj) override;public:static shared_ptr<MonsterStatus> getInstance(){static shared_ptr<MonsterStatus> instance(new MonsterStatus_Worr());return instance;}};class MonsterStatus_Fear : public MonsterStatus{public:void Attacked(int power, Monster *const mainobj) override;public:static shared_ptr<MonsterStatus> getInstance(){static shared_ptr<MonsterStatus> instance(new MonsterStatus_Fear());return instance;}};class MonsterStatus_Dead : public MonsterStatus{public:void Attacked(int power, Monster *const mainobj) override;public:static shared_ptr<MonsterStatus> getInstance(){static shared_ptr<MonsterStatus> instance(new MonsterStatus_Dead());return instance;}};class Monster // 怪物类定义{int m_life;                         // 血量(生命值)shared_ptr<MonsterStatus> m_pState; // 持有状态对象public:Monster(int life, const shared_ptr<MonsterStatus> &pState = MonsterStatus_Feroc::getInstance()) : m_life(life), m_pState(pState) {}public:void Attacked(int power) { m_pState->Attacked(power, this); } // 怪物被攻击public:int GetLife() const { return m_life; }                                               // 获取怪物血量void SetLife(int life) { m_life = life; }                                            // 设置怪物血量shared_ptr<MonsterStatus> getCurrentState() const { return m_pState; }               // 获取怪物当前状态void setCurrentState(const shared_ptr<MonsterStatus> &pState) { m_pState = pState; } // 设置怪物当前状态};void MonsterStatus_Feroc::Attacked(int power, Monster *const mainobj) // 凶悍状态类{int orglife = mainobj->GetLife(); // 暂存原来的怪物血量值用于后续比较if ((orglife - power) > 400)      // 怪物原来处于凶悍状态, 现在依旧处于凶悍状态{// 状态未变mainobj->SetLife(orglife - power); // 怪物剩余的血量cout << "MonsterStatus_Feroc, attackt!" << endl;// 处理其他动作逻辑比如反击}else{// 不管下个状态是啥, 总之不会是凶悍状态, 只可能是不安、恐惧、死亡状态之一, 先无条件转到不安状态去(不安状态中会进行再次判断)mainobj->setCurrentState(MonsterStatus_Worr::getInstance());// mainobj->getCurrentState()->Attacked(power, mainobj);mainobj->Attacked(power);}}void MonsterStatus_Worr::Attacked(int power, Monster *const mainobj) // 不安状态类{int orglife = mainobj->GetLife();if ((orglife - power) > 100) // 怪物原来处于不安状态, 现在依旧处于不安状态{// 状态未变mainobj->SetLife(orglife - power); // 怪物剩余的血量cout << "MonsterStatus_Worr, attackt, help!" << endl;// 处理其他动作逻辑比如反击和不停的呼唤支援}else{// 不管下个状态是啥, 总之不会是凶悍和不安状态, 只可能是恐惧、死亡状态之一, 先无条件转到恐惧状态去mainobj->setCurrentState(MonsterStatus_Fear::getInstance());// mainobj->getCurrentState()->Attacked(power, mainobj);mainobj->Attacked(power);}}void MonsterStatus_Fear::Attacked(int power, Monster *const mainobj) // 恐惧状态类{int orglife = mainobj->GetLife();if ((orglife - power) > 0) // 怪物原来处于恐惧状态, 现在依旧处于恐惧状态{// 状态未变mainobj->SetLife(orglife - power); // 怪物剩余的血量cout << "MonsterStatus_Fear, run!" << endl;// 处理其他动作逻辑比如逃跑}else{// 不管下个状态是啥, 总之不会是凶悍、不安和恐惧状态, 只可能是死亡状态mainobj->setCurrentState(MonsterStatus_Dead::getInstance());// mainobj->getCurrentState()->Attacked(power, mainobj);mainobj->Attacked(power);}}void MonsterStatus_Dead::Attacked(int power, Monster *const mainobj) // 死亡状态类{int orglife = mainobj->GetLife();if (orglife > 0){// 还要把怪物生命值减掉mainobj->SetLife(orglife - power); // 怪物剩余的血量// 处理怪物死亡后事宜比如怪物尸体定时消失等}cout << "dead!" << endl;}
}int main()
{
#if 0using namespace ns1;Monster monster(500, Monster::MonS_Fer);cout << "Monster, MonS_Fer, 500 blood!" << endl;monster.Attacked(20);monster.Attacked(100);monster.Attacked(200);monster.Attacked(170);monster.Attacked(100);monster.Attacked(100);
#endif#if 0using namespace ns2;Monster monster(500);cout << "Monster, MonS_Fer, 500 blood!" << endl;monster.Attacked(20);monster.Attacked(100);monster.Attacked(200);monster.Attacked(170);monster.Attacked(100);monster.Attacked(100);
#endif#if 0using namespace ns3;Monster monster(500);cout << "Monster, MonS_Fer, 500 blood!" << endl;monster.Attacked(20);monster.Attacked(100);monster.Attacked(200);monster.Attacked(170);monster.Attacked(100);monster.Attacked(100);
#endif#if 1using namespace ns4;Monster monster(500);cout << "Monster, MonS_Fer, 500 blood!" << endl;monster.Attacked(20);monster.Attacked(100);monster.Attacked(200);monster.Attacked(170);monster.Attacked(100);monster.Attacked(100);
#endifcout << "Over!\n";return 0;
}