当前位置:网站首页>05 observer mode
05 observer mode
2022-06-27 07:49:00 【zzyzxb】
One : An example of inefficiency caused by traversal problems
#ifdef _DEBUG // Only in Debug( debugging ) In mode
#ifndef DEBUG_NEW
#define DEBUG_NEW new(_NORMAL_BLOCK,__FILE__,__LINE__) // Redefinition new Operator
#define new DEBUG_NEW
#endif
#endif
//#include <boost/type_index.hpp>
using namespace std;
//#pragma warning(disable : 4996)
namespace nmsp1
{
class Fighter; // Class forward declaration
list<Fighter*> g_playerList;
// Player parent class ( Former combatants )
class Fighter
{
public:
Fighter(int tmpID, string tmpName) :m_iPlayerID(tmpID), m_sPlayerName(tmpName) // Constructors
{
m_iFamilyID = -1; //-1 It means that you have not joined any family
}
virtual ~Fighter() {} // Destructor
public:
void SetFamilyID(int tmpID) // When you join a family, you should set up a family ID
{
m_iFamilyID = tmpID;
}
public:
void SayWords(string tmpContent) // The player said something
{
if (m_iFamilyID != -1)
{
// The player belongs to a family , The chat content information should be transmitted to other players in the family
for (auto iter = g_playerList.begin(); iter != g_playerList.end(); ++iter)
{
if (m_iFamilyID == (*iter)->m_iFamilyID)
{
// Other players in the same family should also receive chat messages
NotifyWords((*iter), tmpContent);
}
}
}
}
private:
void NotifyWords(Fighter* otherPlayer, string tmpContent) // Other players have received chat messages from the current player
{
// display information
cout << " The player :" << otherPlayer->m_sPlayerName << " Received player :" << m_sPlayerName << " Chat messages sent :" << tmpContent << endl;
}
private:
int m_iPlayerID; // The player ID, Globally unique
string m_sPlayerName; // Player name
int m_iFamilyID; // family ID
};
//" warrior " Class player , The parent class is Fighter
class F_Warrior :public Fighter
{
public:
F_Warrior(int tmpID, string tmpName) :Fighter(tmpID, tmpName) {} // Constructors
};
//" Master " Class player , The parent class is Fighter
class F_Mage :public Fighter
{
public:
F_Mage(int tmpID, string tmpName) :Fighter(tmpID, tmpName) {} // Constructors
};
}
int main()
{
// Create gamers
nmsp1::Fighter* pplayerobj1 = new nmsp1::F_Warrior(10, " Zhang San "); // In the actual game, a lot of data is taken from the database
pplayerobj1->SetFamilyID(100); // Suppose the player's family ID yes 100
nmsp1::g_playerList.push_back(pplayerobj1); // Add to the global player list
nmsp1::Fighter* pplayerobj2 = new nmsp1::F_Warrior(20, " Li Si ");
pplayerobj2->SetFamilyID(100);
nmsp1::g_playerList.push_back(pplayerobj2);
nmsp1::Fighter* pplayerobj3 = new nmsp1::F_Mage(30, " Wang Wu ");
pplayerobj3->SetFamilyID(100);
nmsp1::g_playerList.push_back(pplayerobj3);
nmsp1::Fighter* pplayerobj4 = new nmsp1::F_Mage(50, " Zhao Liu ");
pplayerobj4->SetFamilyID(200); // Zhao Liu and the first three belong to two different families
nmsp1::g_playerList.push_back(pplayerobj4);
// When a player chats , People of the same race should receive this message
pplayerobj1->SayWords(" The whole clan immediately gathered in the swamp , Prepare to attack !");
// Release resources
delete pplayerobj1;
delete pplayerobj2;
delete pplayerobj3;
delete pplayerobj4;
std::cout << " Main thread execution completed \n";
}
Two : Bring in the observer (Observer) Pattern
The code for using the observer design pattern is as follows
#ifdef _DEBUG // Only in Debug( debugging ) In mode
#ifndef DEBUG_NEW
#define DEBUG_NEW new(_NORMAL_BLOCK,__FILE__,__LINE__) // Redefinition new Operator
#define new DEBUG_NEW
#endif
#endif
//#include <boost/type_index.hpp>
using namespace std;
//#pragma warning(disable : 4996)
namespace nmsp1
{
class Fighter; // Class forward declaration
list<Fighter*> g_playerList;
// Player parent class ( Former combatants )
class Fighter
{
public:
Fighter(int tmpID, string tmpName) :m_iPlayerID(tmpID), m_sPlayerName(tmpName) // Constructors
{
m_iFamilyID = -1; //-1 It means that you have not joined any family
}
virtual ~Fighter() {} // Destructor
public:
void SetFamilyID(int tmpID) // When you join a family, you should set up a family ID
{
m_iFamilyID = tmpID;
}
public:
void SayWords(string tmpContent) // The player said something
{
if (m_iFamilyID != -1)
{
// The player belongs to a family , The chat content information should be transmitted to other players in the family
for (auto iter = g_playerList.begin(); iter != g_playerList.end(); ++iter)
{
if (m_iFamilyID == (*iter)->m_iFamilyID)
{
// Other players in the same family should also receive chat messages
NotifyWords((*iter), tmpContent);
}
}
}
}
private:
void NotifyWords(Fighter* otherPlayer, string tmpContent) // Other players have received chat messages from the current player
{
// display information
cout << " The player :" << otherPlayer->m_sPlayerName << " Received player :" << m_sPlayerName << " Chat messages sent :" << tmpContent << endl;
}
private:
int m_iPlayerID; // The player ID, Globally unique
string m_sPlayerName; // Player name
int m_iFamilyID; // family ID
};
//" warrior " Class player , The parent class is Fighter
class F_Warrior :public Fighter
{
public:
F_Warrior(int tmpID, string tmpName) :Fighter(tmpID, tmpName) {} // Constructors
};
//" Master " Class player , The parent class is Fighter
class F_Mage :public Fighter
{
public:
F_Mage(int tmpID, string tmpName) :Fighter(tmpID, tmpName) {} // Constructors
};
}
namespace nmsp2
{
class Fighter; // Class forward declaration
class Notifier // Notifier parent class
{
public:
virtual void addToList(Fighter* player) = 0; // Add the players to be notified to the list
virtual void removeFromList(Fighter* player) = 0; // Remove players from the list who do not want to be notified
virtual void notify(Fighter* talker, string tmpContent) = 0; // Some details of the notice
virtual ~Notifier() {}
};
// Player parent class
class Fighter
{
public:
Fighter(int tmpID, string tmpName) :m_iPlayerID(tmpID), m_sPlayerName(tmpName) // Constructors
{
m_iFamilyID = -1; //-1 It means that you have not joined any family
}
virtual ~Fighter() {} // Destructor
public:
void SetFamilyID(int tmpID) // When you join a family, you should set up a family ID
{
m_iFamilyID = tmpID;
}
int GetFamilyID() // Get the family ID
{
return m_iFamilyID;
}
public:
void SayWords(string tmpContent, Notifier* notifier) // The player said something
{
notifier->notify(this, tmpContent);
}
// Notify the player to receive the chat message sent by other players , Virtual functions , Subclasses can be overridden to implement different functions
virtual void NotifyWords(Fighter* talker, string tmpContent)
{
// display information
cout << " The player :" << m_sPlayerName << " Received player :" << talker->m_sPlayerName << " Chat messages sent :" << tmpContent << endl;
}
private:
int m_iPlayerID; // The player ID, Globally unique
string m_sPlayerName; // Player name
int m_iFamilyID; // family ID
};
//" warrior " Class player , The parent class is Fighter
class F_Warrior :public Fighter
{
public:
F_Warrior(int tmpID, string tmpName) :Fighter(tmpID, tmpName) {} // Constructors
};
//" Master " Class player , The parent class is Fighter
class F_Mage :public Fighter
{
public:
F_Mage(int tmpID, string tmpName) :Fighter(tmpID, tmpName) {} // Constructors
};
// Chat message notifier
class TalkNotifier :public Notifier
{
public:
// Add players to the family list
virtual void addToList(Fighter* player)
{
int tmpfamilyid = player->GetFamilyID();
if (tmpfamilyid != -1) // Joined a family
{
auto iter = m_familyList.find(tmpfamilyid);
if (iter != m_familyList.end())
{
// The family id stay map There is already
iter->second.push_back(player); // Directly add the player to the family
}
else
{
// The family id stay map Does not exist in the
list<Fighter*> tmpplayerlist;
m_familyList.insert(make_pair(tmpfamilyid, tmpplayerlist)); // With this family id by key, Add entries to map in
m_familyList[tmpfamilyid].push_back(player); // Add the first player to the family
}
}
}
// Remove players from the family list
virtual void removeFromList(Fighter* player)
{
int tmpfamilyid = player->GetFamilyID();
if (tmpfamilyid != -1) // Joined a family
{
auto iter = m_familyList.find(tmpfamilyid);
if (iter != m_familyList.end())
{
m_familyList[tmpfamilyid].remove(player);
}
}
}
// A player in the family said something , Call this function to notify everyone in the family
virtual void notify(Fighter* talker, string tmpContent) //talker It's the talking player
{
int tmpfamilyid = talker->GetFamilyID();
if (tmpfamilyid != -1) // Joined a family
{
auto itermap = m_familyList.find(tmpfamilyid);
if (itermap != m_familyList.end())
{
// Traverse all members of the family to which the player belongs
for (auto iterlist = itermap->second.begin(); iterlist != itermap->second.end(); ++iterlist)
{
(*iterlist)->NotifyWords(talker, tmpContent);
}
}
}
}
private:
//map Medium key Means family id,value Represents the list of all players in the family
map<int, list<Fighter*>> m_familyList;
};
}
int main()
{
// Create gamers
nmsp2::Fighter* pplayerobj1 = new nmsp2::F_Warrior(10, " Zhang San "); // In the actual game, a lot of data is taken from the database .
pplayerobj1->SetFamilyID(100); // Suppose the family of the player's family ID yes 100
nmsp2::Fighter* pplayerobj2 = new nmsp2::F_Warrior(20, " Li Si ");
pplayerobj2->SetFamilyID(100);
nmsp2::Fighter* pplayerobj3 = new nmsp2::F_Mage(30, " Wang Wu ");
pplayerobj3->SetFamilyID(100);
nmsp2::Fighter* pplayerobj4 = new nmsp2::F_Mage(50, " Zhao Liu ");
pplayerobj4->SetFamilyID(200); // Zhao Liu and the first three belong to two different families
// Create notifier
nmsp2::Notifier* ptalknotify = new nmsp2::TalkNotifier();
// Players are added to the family list , Only in this way can we receive family chat messages
ptalknotify->addToList(pplayerobj1);
ptalknotify->addToList(pplayerobj2);
ptalknotify->addToList(pplayerobj3);
ptalknotify->addToList(pplayerobj4);
// A gamer chats , People of the same race should receive this message
pplayerobj1->SayWords(" The whole clan immediately gathered in the swamp , Prepare to attack !", ptalknotify);
cout << " Wang Wu doesn't want to receive any more chat messages from other members of the family ---" << endl;
ptalknotify->removeFromList(pplayerobj3); // Remove Wang Wu from the family list
pplayerobj2->SayWords(" Please follow the instructions of the patriarch , Go to the swamp !", ptalknotify);
// Release resources
delete pplayerobj1;
delete pplayerobj2;
delete pplayerobj3;
delete pplayerobj4;
delete ptalknotify;
std::cout << " Main thread execution completed \n";
}
<1>pplayerobj1->SayWords(“ The whole clan immediately gathered in the swamp , Prepare to attack !”,ptalknotify);
<2>notifier->notify(this, tmpContent);
<3>int tmpfamilyid = talker->GetFamilyID();
<4>auto itermap = m_familyList.find(tmpfamilyid);
<5>for (auto iterlist = itermap->second.begin(); iterlist != itermap->second.end(); ++iterlist) // Traverse list Containers
(*iterlist)->NotifyWords(talker,tmpContent);
<6>cout << “ The player :” << m_sPlayerName << " Received player :" << talker->m_sPlayerName << " Chat messages sent :" << tmpContent << endl;
Observer design pattern definition ( Realize the intention ): Defines a one-to-many dependency between objects , When the state of an object changes , All objects that depend on it are automatically notified .
Release - subscribe (Publish-Subscribe)

Observer mode UML chart

Observer pattern without abstracting notifier UML chart
The four roles of the observer model
a)Subject( The theme ): Observe the target , Here it means Notifier class .
b)ConcreteSubject( Specific themes ): Here it means TalkNotifier class .
c)Observer( The observer ): Here it means Fighter class .
d)ConcreteObserver( Concrete observer ): Here it means F_Warrior and F_Mage Subclass .

Observer pattern role diagram
The characteristics of the observer model
a) An abstract coupling is established between the observer and the observed object .
b) The observation target sends a notification to all observers in the observer list .
c) You can add new observers or observation targets by adding code , Comply with opening and closing principle .
3、 ... and : Apply Lenovo
a) Rescue the escort cart of family members .
b) Recommend the news to readers who like it .
c) By changing the graphics drawn by itself to truly reflect the company's sales data .
d) The turret will only be right 30 Players within meters ( Players in the list ) The attack .
边栏推荐
- Mobile security tools -jad
- js例题打印1-100之间所有7的倍数的个数及总和
- js成绩奖惩例题
- 无论LCD和OLED显示技术有多好,都无法替代这个古老的显示数码管
- 【批处理DOS-CMD命令-汇总和小结】-批处理命令中的参数%0、%1、%2、%[0-9]、%0-9和批处理命令参数位置切换命令shift,dos命令中操作符%用法
- cookie加密7 fidder分析阶段
- 闭包问题
- JS to determine whether the result is qualified, the range is 0-100, otherwise re-enter
- js中判断奇偶的函数,求圆面积的函数
- js中如何查看程序运行时间(计时器)
猜你喜欢

Import and export database related tables from the win command line

No matter how good LCD and OLED display technologies are, they cannot replace this ancient display nixie tube

【批处理DOS-CMD命令-汇总和小结】-将文件夹映射成虚拟磁盘——subst

File and multipartfile overview

基础知识 | js基础

【11. 二维差分】

Yarn create vite reports an error 'd:\program' which is neither an internal or external command nor a runnable program or batch file

js打印99乘法表

Common operation and Principle Exploration of stream

Basic knowledge | JS Foundation
随机推荐
"Short video" Linxia fire rescue detachment carries out fire safety training
JS use the switch statement to output the corresponding English day of the week according to 1-7
What is futures reverse documentary?
2. QT components used in the project
js中输入三个值,并且由小到大输出
js用switch语句根据1-7输出对应英文星期几
Error in idea connection database
认识O(NlogN)的排序
The first part of the construction of the defense system of attack and defense exercise is the introduction and the four stages of Defense
【10. 差分】
盲測調查顯示女碼農比男碼農更優秀
JS performance reward and punishment examples
语音信号处理-概念(四):傅里叶变换、短时傅里叶变换、小波变换
The IPO of Yefeng pharmaceutical was terminated: Yu Feng, the actual controller who had planned to raise 540million yuan, made P2P investment
盲测调查显示女码农比男码农更优秀
[compilation principles] review outline of compilation principles of Shandong University
No matter how good LCD and OLED display technologies are, they cannot replace this ancient display nixie tube
游戏六边形地图的实现
How to view program running time (timer) in JS
Cookie加密6