C++ 相互感知的对象集合
这是一个宽泛的问题,但出于我自己的理解,我决定把它扔出去 有谁能推荐设计,或者甚至是普遍接受的设计模式,用于需要各种对象相互感知的情况 要使用人物/社区模拟作为类比,当您有X个人物对象,其中X可以动态增长/收缩,并且每个人物对象都持有对其他对象的看法或与其他对象的关系时,应用的最佳模式是什么 在编程语法之外,我可以使用一个X×X网格来表示每个人之间的关系(喜欢、不喜欢、没见过等等)。我基本上是想在代码中将其作为一个单独的对象来实现的,每个person对象在每次创建新对象时都会更新,但这似乎是一个完全不优雅的解决方案。这里有人有什么建议吗 其次,如果我收集了每个人的“库存”或他们携带的物品,我想我可以创建每个人的库存作为类的列表成员;此链接列表将随着此人拥有的对象的增长和收缩而增长和收缩 人们可以很容易地查询到他们携带的物品,但我无法找到一种有效的方法来实现相反的查询;也就是说,我希望能够查询一个项目,并找到哪些人拥有该项目 我确实读过这个问答: …但我不确定它是否完全适用于我的情况 有人能提供一些建议吗 谢谢C++ 相互感知的对象集合,c++,design-patterns,C++,Design Patterns,这是一个宽泛的问题,但出于我自己的理解,我决定把它扔出去 有谁能推荐设计,或者甚至是普遍接受的设计模式,用于需要各种对象相互感知的情况 要使用人物/社区模拟作为类比,当您有X个人物对象,其中X可以动态增长/收缩,并且每个人物对象都持有对其他对象的看法或与其他对象的关系时,应用的最佳模式是什么 在编程语法之外,我可以使用一个X×X网格来表示每个人之间的关系(喜欢、不喜欢、没见过等等)。我基本上是想在代码中将其作为一个单独的对象来实现的,每个person对象在每次创建新对象时都会更新,但这似乎是一个
--关系数据库正是为此而建立的。如果你不熟悉它,请阅读 可以将数据库与多个表一起使用。其中一个表是“person”,它包含人的基本属性和一个id 要对“met”之类的关系建模,请创建一个名为
met
的表,该表有两列,其中包含两个相互认识的人的ID
数据库针对“查找所有见过John的人”等查询进行了大量优化。如果不想安装客户机/服务器数据库,可以使用基于文件的数据库,如GOF书中的典型示例就是使用该模式。他们给出的示例是,GUI窗口/对话框(中介器)跟踪其控件(有时称为同事),并通知控件相关事件,如窗口大小调整等。我相信该示例扩展到允许控件查询中介器以获取其他控件的信息 如果希望对象能够跟踪对象的特定实例,则观察者模式(如cbamber85所示)非常有用。但是,对于对象对象中发生的事件的一般信息,您可能需要考虑使用中介器。
关于您的具体问题,调解人可能会帮助跟踪一般人群的变化(增长或收缩)。如果关系仅仅是沟通,而不是真正的终身所有权,并且您不希望每个人都能够自动与每个人交谈,那么接口代理通常是一个良好的开端。这些只是中间类,它们拥有与同事通信的方式,并在任何一方的生命周期发生变化时提供通知。这些代码通常是单向的,但当您将它们配对并添加更多的粘合代码时,它们就会变成双向的 你有课吗
class ColleagueProxy
{
private:
// a pointer to the Colleague
// it can be a naked pointer since it does not deal with lifetime
Colleague friend_;
// a callback for when death comes to the colleague
typedef std::function<void (ColleagueProxy *)> DeathHandler;
DeathHandler deathCallback_;
// an identifier for friends to know me by
std::string id_;
public:
// ctor takes a colleague and a callback for when colleague dies
// ctor notifies friend of new proxy following - in case that is useful info
ColleagueProxy(Colleague * friend, DeathHandler callback, std::string const& myName) :
friend_(friend),
deathCallback_(callback)
{
if (friend)
friend_->proxyConnecting(this);
}
// dtor may notify friend as well
~ColleagueProxy()
{
if (friend)
friend_->proxyLeaving(this);
}
// the communication interface
void sayHi()
{
if (friend)
friend_->sayHi(this);
}
// ...
// my name badge
std::string id() { return id_; }
// a way for the friend to say goodbye
void Goodbye()
{
deathCallback_(this);
}
};
class collagueproxy
{
私人:
//指向同事的指针
//它可以是裸指针,因为它不处理生存期
同事朋友!;
//同事死亡时的回电
typedef std::函数DeathHandler;
死亡处理者死亡;
//朋友认识我的标识符
std::字符串id;
公众:
//ctor接收一位同事,并在同事去世时回拨一次电话
//ctor通知朋友新的代理跟踪-以防这是有用的信息
collagueproxy(同事*朋友,死亡处理程序回调,std::string const&myName):
朋友(朋友),,
死亡回调(回调)
{
如果(朋友)
朋友->代理连接(此);
}
//dtor也可以通知朋友
~collagueproxy()
{
如果(朋友)
朋友->proxyLeaving(这个);
}
//通信接口
void sayHi()
{
如果(朋友)
朋友->sayHi(这个);
}
// ...
//我的名牌
std::string id(){return id_;}
//朋友道别的一种方式
作废再见()
{
死亡(这个);
}
};
然后同事们会存储这些通信代理
class Colleague
{
private:
std::map<std::string, std::shared_ptr<ColleagueProxy>> friends_;
std::vector<std::shared_ptr<ColleagueProxy>> colleaguesWhoConsiderMeAFriend_;
void GoodbyeCallback(ColleagueProxy * that)
{
// search through friends_ and remove that
}
}
班级同事
{
私人:
std::映射朋友;
std::病媒菌群,其主要成分为:;
void GoodbyeCallback(collagueproxy*that)
{
//在好友中搜索并删除该好友
}
}
您可以通过一个管理器类自动化一些清理部分,因此如果您有不同的动态类型,就不会复制代码。不过,如果你只有一个同事类型,那就没有必要了。经理类可能有用的另一个有用原因是它可以创建同事,这可能会应用限制或其他可见性规则
这种设计的要点是允许针对每个连接定制通信机制(每个代理对象可能持有特定于连接的状态)。这可以应用于意见(如原始问题)和许多其他事情。您不必担心循环依赖性,因为生命周期管理不是连接的一部分(例如,如果您只是将一个结构与一个共享的ptr存储到朋友,其中循环依赖性可能会导致孤立循环的问题)
如果您真的想让每个人都不受限制地看到其他人,那么在
class Person {
struct Relationship {
// whatever
};
std::map<Person*, Relationship> relationships;
public:
Person() {}
void Meet(Person* other) {
// think about it
relationships[other] = ...;
}
~Person() {
// Loop through the map and ensure no dud relationships
for(auto& pair : relationships) {
pair.first->relationships.erase(this);
}
}
};
class PersonManager {
struct Item { ... };
std::set<Item, std::set<Person*>> items; // set for no dupes
public:
void AddToInventory(Item i, Person* p) {
items[i].insert(p);
}
std::vector<Person*> PeopleWithItem(Item i) {
return std::vector<Person*>(items[i].begin(), items[i].end());
}
};