Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 相互感知的对象集合_C++_Design Patterns - Fatal编程技术网

C++ 相互感知的对象集合

C++ 相互感知的对象集合,c++,design-patterns,C++,Design Patterns,这是一个宽泛的问题,但出于我自己的理解,我决定把它扔出去 有谁能推荐设计,或者甚至是普遍接受的设计模式,用于需要各种对象相互感知的情况 要使用人物/社区模拟作为类比,当您有X个人物对象,其中X可以动态增长/收缩,并且每个人物对象都持有对其他对象的看法或与其他对象的关系时,应用的最佳模式是什么 在编程语法之外,我可以使用一个X×X网格来表示每个人之间的关系(喜欢、不喜欢、没见过等等)。我基本上是想在代码中将其作为一个单独的对象来实现的,每个person对象在每次创建新对象时都会更新,但这似乎是一个

这是一个宽泛的问题,但出于我自己的理解,我决定把它扔出去

有谁能推荐设计,或者甚至是普遍接受的设计模式,用于需要各种对象相互感知的情况

要使用人物/社区模拟作为类比,当您有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());
    }
};