《C++新经典设计模式》之第5章 观察者模式

阅读: 评论:0

《C++新经典设计模式》之第5章 观察者模式

《C++新经典设计模式》之第5章 观察者模式

《C++新经典设计模式》之第5章 观察者模式

        • 观察者模式.cpp

观察者模式.cpp
#include <iostream>
#include <list>
#include <map>
#include <memory>
using namespace std;// 对象状态变化时,通过公告或广播方式通知一系列相关对象,实现对象之间的联动
// 4种角色
// Subject(主题),观察目标,被观察对象,Notifier类,addToList、removeFromList
// ConcreteSubject(具体主题),维护观察者列表,状态改变时,notify通知各个观察者,TalkNotifier
// Observer(观察者),被观察对象状态变化时,观察者自身收到通知,Fighter
// ConcreteObserver(具体观察者),F_Warrior、F_Magenamespace ns1
{class Fighter;static list<shared_ptr<Fighter>> g_playerList;class Fighter // 战斗者玩家{int m_iPlayerID;      // 玩家ID,全局唯一string m_sPlayerName; // 玩家名字int m_iFamilyID{-1};  // 家族ID, -1表示没加入任何家族private:void ReceiveMessage(const Fighter *const otherPlayer, const string &tmpContent) const{cout << "receive message: " << tmpContent << ", from " << otherPlayer->m_sPlayerName << ", by " << m_sPlayerName << endl;}void NotifyWords(const shared_ptr<Fighter> &otherPlayer, const string &tmpContent) const // //其他玩家收到了当前玩家的聊天信息{if (() != this)otherPlayer->ReceiveMessage(this, tmpContent); // 同一个家族的其他玩家也应该收到聊天信息}public:Fighter(int tmpID, const string &tmpName) : m_iPlayerID(tmpID), m_sPlayerName(tmpName) {}virtual ~Fighter() {}public:void SetFamilyID(int tmpID) { m_iFamilyID = tmpID; } // 加入家族时设置家族IDpublic:void SayWords(const string &tmpContent) const // 玩家说了某句话{if (m_iFamilyID != -1)// 该玩家属于某个家族,应该把聊天内容信息传送给该家族的其他玩家for (auto iter = g_playerList.cbegin(); iter != d(); ++iter)if (m_iFamilyID == (*iter)->m_iFamilyID)NotifyWords((*iter), tmpContent); // 同一个家族的其他玩家也应该收到聊天信息}};class F_Warrior : public Fighter // “战士”类玩家{public:F_Warrior(int tmpID, const string &tmpName) : Fighter(tmpID, tmpName) {}};class F_Mage : public Fighter // “法师”类玩家{public:F_Mage(int tmpID, const string &tmpName) : Fighter(tmpID, tmpName) {}};
}namespace ns2
{class Fighter; // 类前向声明class Notifier // 通知器父类{public:virtual ~Notifier() {}virtual void addToList(const shared_ptr<Fighter> &player) = 0;                        // 把要被通知的玩家加到列表中virtual void removeFromList(const shared_ptr<Fighter> &player) = 0;                   // 把不想被通知的玩家从列表中去除virtual void notify(const Fighter *const talker, const string &tmpContent) const = 0; // 通知的一些细节信息};class Fighter{int m_iPlayerID;      // 玩家ID,全局唯一string m_sPlayerName; // 玩家名字int m_iFamilyID{-1};  // 家族ID,-1表示没加入任何家族private:void ReceiveMessage(const Fighter *const otherPlayer, const string &tmpContent) const{cout << "receive message: " << tmpContent << ", from " << otherPlayer->m_sPlayerName << ", by " << m_sPlayerName << endl;}public:virtual ~Fighter() {}Fighter(int tmpID, const string &tmpName) : m_iPlayerID(tmpID), m_sPlayerName(tmpName) {}public:void SetFamilyID(int tmpID) { m_iFamilyID = tmpID; }int GetFamilyID() const { return m_iFamilyID; }void SayWords(const string &tmpContent, const shared_ptr<Notifier> &notifier) const // 玩家说了某句话{notifier->notify(this, tmpContent);}public:void NotifyWords(const Fighter *const talker, const string &tmpContent) const // 其他玩家收到了当前玩家的聊天信息{if (talker != this)ReceiveMessage(talker, tmpContent); // 同一个家族的其他玩家也应该收到聊天信息}};class F_Warrior : public Fighter // “战士”类玩家{public:F_Warrior(int tmpID, const string &tmpName) : Fighter(tmpID, tmpName) {}};class F_Mage : public Fighter // “法师”类玩家{public:F_Mage(int tmpID, const string &tmpName) : Fighter(tmpID, tmpName) {}};class TalkNotifier : public Notifier // 聊天信息通知器{map<int, list<shared_ptr<Fighter>>> m_familyList; // key: 家族id,value: 玩家列表public:void addToList(const shared_ptr<Fighter> &player) override // 将玩家增加到家族列表中来{int tmpfamilyid = player->GetFamilyID();if (tmpfamilyid != -1) // 加入了某个家族{auto iter = m_familyList.find(tmpfamilyid);if (iter != d()) // 该家族id在map中已经存在{iter->second.push_back(player); // 直接把该玩家加入到该家族}else // 该家族id在map中不存在{list<shared_ptr<Fighter>> tmpplayerlist;m_familyList.insert(make_pair(tmpfamilyid, tmpplayerlist)); // 以该家族id为key,增加条目到map中m_familyList[tmpfamilyid].push_back(player);                // 向该家族中增加第一个玩家}}}void removeFromList(const shared_ptr<Fighter> &player) override // 将玩家从家族列表中删除{int tmpfamilyid = player->GetFamilyID();if (tmpfamilyid != -1) // 加入了某个家族{auto iter = m_familyList.find(tmpfamilyid);if (iter != d()){m_familyList[tmpfamilyid].remove(player);if (m_familyList[tmpfamilyid].empty()) // 该家族中没有玩家了,应该从map中删除该家族ase(tmpfamilyid);}}}// 家族中某玩家说了句话,调用该函数来通知家族中所有人void notify(const Fighter *const talker, const string &tmpContent) const override // talker是讲话的玩家{int tmpfamilyid = talker->GetFamilyID();if (tmpfamilyid != -1){auto itermap = m_familyList.find(tmpfamilyid);if (itermap != d())// 遍历该玩家所属家族的所有成员for (auto iterlist = itermap->second.cbegin(); iterlist != itermap-&d(); ++iterlist)(*iterlist)->NotifyWords(talker, tmpContent);}}};
}int main()
{
#if 0using namespace ns1;// 创建游戏玩家shared_ptr<Fighter> pplayerobj1(new F_Warrior(10, "1")); // 实际游戏中很多数据取自数据库pplayerobj1->SetFamilyID(100);                           // 假设该玩家所在的家族的家族ID是100g_playerList.push_back(pplayerobj1);                     // 加入到全局玩家列表中shared_ptr<Fighter> pplayerobj2(new F_Warrior(20, "2"));pplayerobj2->SetFamilyID(100);g_playerList.push_back(pplayerobj2);shared_ptr<Fighter> pplayerobj3(new F_Mage(30, "3"));pplayerobj3->SetFamilyID(100);g_playerList.push_back(pplayerobj3);shared_ptr<Fighter> pplayerobj4(new F_Mage(40, "4"));pplayerobj4->SetFamilyID(200); // pplayerobj4和前面三人属于两个不同的家族g_playerList.push_back(pplayerobj4);// 某游戏玩家聊天,同族人都应该收到该信息pplayerobj1->SayWords("come on, attact!");
#endif#if 1using namespace ns2;// 创建游戏玩家shared_ptr<Fighter> pplayerobj1(new F_Warrior(10, "1"));pplayerobj1->SetFamilyID(100);shared_ptr<Fighter> pplayerobj2(new F_Warrior(20, "2"));pplayerobj2->SetFamilyID(100);shared_ptr<Fighter> pplayerobj3(new F_Mage(30, "3"));pplayerobj3->SetFamilyID(100);shared_ptr<Fighter> pplayerobj4(new F_Mage(40, "4"));pplayerobj4->SetFamilyID(200);// 创建通知器shared_ptr<Notifier> ptalknotify(new TalkNotifier());// 玩家增加到家族列表中来,这样才能收到家族聊天信息ptalknotify->addToList(pplayerobj1);ptalknotify->addToList(pplayerobj2);ptalknotify->addToList(pplayerobj3);ptalknotify->addToList(pplayerobj4);// 某游戏玩家聊天,同族人都应该收到该信息pplayerobj1->SayWords("come on, attack!", ptalknotify);cout << "leave---" << endl;ptalknotify->removeFromList(pplayerobj3); // 将pplayerobj3从家族列表中删除pplayerobj2->SayWords("listen, go together!", ptalknotify);
#endifcout << "Over!n";return 0;
}

本文发布于:2024-02-02 13:43:54,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170685263544189.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:模式   观察者   经典
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23