存储各种类型的对象之间的1:1关系:解耦和高性能 [英] store many of relation 1:1 between various type of objects : decoupling & high performance

查看:106
本文介绍了存储各种类型的对象之间的1:1关系:解耦和高性能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有300多个课程.它们在某些方面是相关的.

I have 300+ classes. They are related in some ways.

为简单起见,所有关系均为1:1.
这是一个示例图.

For simplicity, all relation are 1:1.
Here is a sample diagram.

(在实际情况下,大约有50个关联对.)

注意:在某些情况下,某些关系可能不存在.
例如,某些hen与任何food不相关.

Note: For some instances, some relation may not exist.
For example, some hens don't relate to any food.

注意2 :无链接=永不,例如每个egg都不与任何cage相关.
这样的关系将永远不会被添加/删除/查询.

Note2: No link = never, e.g. every egg doesn't relate to any cage.
Such relation will never be added/removed/queried.

如何优雅地存储它们之间的关系?
我的所有四个想法(如下)似乎都有缺点.

How to store relation between them elegantly?
All 4 of my ideas (below) seem to have disadvantages.

此处是一个相关问题,但具有1:N且只有1个关系.

Here is a related question but with 1:N and only 1 relation.

这些是半伪代码.

我的第一个想法是相互添加指针.

My first thought is to add pointer(s) to each other.

Chick.h:-

class Egg;
class Food;
class Chick{  Egg* egg; Food* food;}

Hen.h:-

class Egg; class Cage; class Food;
class Hen{ Egg* egg; Cage* cage; Food* food;}

添加/删除关系和查询非常便宜,例如:-

It is very cheap to add/remove relation and query, e.g. :-

int main(){
    Hen* hen;    ...    Egg* egg=hen->egg;
}

效果很好,但是随着程序的增长,我想将它们解耦.
粗略地说,Hen.h不应包含单词Egg,反之亦然.

It works good, but as my program grow, I want to decouple them.
Roughly speaking, Hen.h should not contain word Egg, and vice versa.

有很多主意,但似乎没有一个好主意.
我将为每个变通方法显示一个简短的摘要,然后总结优点和优点;问题末尾的缺点.

There are many ideas, but none seems very good.
I will show a brief snippet for each work-around then summarizes pros & cons at the end of question.

使用std::unordered_map.
它成为我程序的瓶颈. (在发布模式下进行了剖析)

Use std::unordered_map.
It becomes a bottle neck of my program. (profiled in release mode)

class Egg{}; class Hen{};  //empty (nice)
.....
int main(){
    std::unordered_map<Hen*,Egg*> henToEgg;
    std::unordered_map<Egg*,Hen*> eggToHen;
    ....
    Hen* hen;    ...    Egg* egg=henToEgg[hen];
}

Version 3 Mediator-single

将每个关系的每个实体存储在单个大调解器中.
浪费大量内存用于空插槽(例如Egg具有henFood_hen插槽).
每个实体的总浪费= type-of-relation-pair * 2 * 4字节(如果以32位运行).

Version 3 Mediator-single

Store every relation in a single big mediator for every entity.
Waste a lot of memory for empty slots (e.g. Egg has henFood_hen slot).
Total waste = type-of-relation-pair*2*4 bytes (if run at 32 bits) in every entity.

class Mediator {
    Egg* eggHen_egg=nullptr;
    Hen* eggHen_hen=nullptr;
    Hen* henFood_hen=nullptr;
    Food* henFood_food=nullptr;
    //... no of line = relation * 2
};
class Base{public: Mediator m;};
class Egg : public Base{};  //empty (nice)
class Hen : public Base{}; 
int main(){
     Hen* hen;    ...    Egg* egg=hen->eggHen_egg;
}

版本4介体数组(类似于3)

尝试标准化-高灵活性.

Version 4 Mediator-array (similar as 3)

Try to standardize - high flexibility.

class Mediator {
    Base* ptrLeft[5];
    Base* ptrRight[5];
};
class Base{public: Mediator m;};
class Egg : public Base{};  //empty (nice)
class Hen : public Base{}; 
int main(){
     enum RELA_X{RELA_HEN_EGG,RELA_HEN_CAGE,RELA_EGG_CHICK, .... };
     Hen* hen;    ...    
     Egg* egg=hen->m.ptrRight[RELA_HEN_EGG]; 
     //^ get right of "hen-egg" === get "egg" from "hen"
     //^ can be encapsulated for more awesome calling
}

优点&缺点

绿色(+)很好.红色(-)不好.

Pros & Cons

Green (+) are good. Red (-) are bad.

:我正在使用实体组件用于60fps游戏.
它是一个持久性数据库:用于游戏整个生命周期的单个实例.

I am using Entity-Component for a 60fps game.
It is a persistent database : a single instance used for the entire life of a game.

Edit2 :所有关系都是弱关系,而不是 is-a 或强力的std::unique_ptr所有权. (谢谢沃尔特)

All of the relation are weak relation rather than is-a or strong std::unique_ptr ownership. (Thank Walter)

  • 一个hen 位于一个cage中.
    某些hens不在任何cage中,而某些cages为空.
  • 一个chick 来自一个egg.
    但是,有些chicks不是来自任何egg(它们只是从天上掉下来的),
    还有一些eggs不够幸运,无法成为chick.
  • 一个hen和一个chick 正在进食一个(可能是相同的)盘子food.
    某些food印版只是准备好但未送达.
  • A hen is in a cage.
    Some hens are not in any cage, and some cages are empty.
  • A chick come from an egg.
    However, some chicks didn't come from any egg (they are just dropped from sky),
    and some eggs are not lucky enough to become chick.
  • A hen and a chick are eating a (probably same) plate of food.
    Some food plates are just prepared but not served.

Edit3 :为每个对象分配一个整数ID可能是个好主意.
(感谢Oliv,ahoxha和Simone Cifani)

Assign an integer id for each object can be a good idea.
(Thank Oliv, ahoxha, and Simone Cifani)

Edit4 :: 无需提供可编译的代码,只需一个基本部分/概念就足够了.

: No need to provide a compilable code, just an essential part / concept is enough.

推荐答案

根据要求,如果您只有一对一的关系,那么在我看来,它就像一张图表.在这种情况下,如果人口稠密(有很多关系),我将使用图的矩阵表示形式.在下表中,我分别将数字0到4关联到实体(母鸡,笼子,食物,鸡蛋和小鸡).如果存在Hen-Egg关系,则矩阵在位置matrix[0][3]处将为1,如果不存在,则值将为0(您可以选择自己选择的值来决定如何判断该关系何时存在或没有).如果关系是无向的,则只需要矩阵的一侧(例如,上三角).

Based on the requirements, if you have only one-to-one relations, then it sounds to me like a graph. In this case, if it is densely populated (there are many relations), I would use the matrix representation of the graph. In the tables below, I have associated numbers 0 through 4 to the entities (Hen, Cage, Food, Egg and Chick) respectively. If the relation Hen - Egg exists, then the matrix will have a 1 at the position matrix[0][3], if it doesn't then the value would be 0 (you can choose values of your choice to decide how to tell when the relation exists or doesn't). If the relations are undirected, then you only need one side of the matrix (the upper triangle, for example).

+---------------------------------+
| Hen | Cage | Food | Egg | Chick |
+---------------------------------+
|  0  |  1   |  2   |  3  |   4   |
+---------------------------------+

      0   1   2   3   4
    +--------------------+
  0 | 0 | 1 | 0 | 1 | 1  |
    +---+---+---+---+----+
  1 | 0 | 0 | 0 | 1 | 1  |
    +---+---+---+---+----+
  2 | 0 | 0 | 0 | 0 | 1  |
    +---+---+---+---+----+
  3 | 0 | 0 | 0 | 0 | 1  |
    +---+---+---+---+----+
  4 | 0 | 0 | 0 | 0 | 0  |
    +--------------------+

此解决方案的不足之处在于内存使用情况,尤其是在矩阵包含很多0(不存在关系)的情况下;您将不必要地占用大量空间.在这种情况下,您可以使用图形的链表表示形式.

The downside of this solution hides in the memory usage, especially if the matrix contains a lot of 0's (relations that don't exist); you would be unnecessarily occupying a lot of space. In this case you may use the linked-list representation of the graphs.

这篇关于存储各种类型的对象之间的1:1关系:解耦和高性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆