数据库中的多态性

问题描述 投票:0回答:2

我想为一组玩家建模一个数据库实体。 每个玩家都应该拥有:

  • 一些固定字段(姓名、角色……)
  • 多个技能等级可变字段(如果角色是ATK,技能应该是stat1和stat2;如果角色是DEF,技能应该是stat3和stat4)。

实现这样一个实体的最佳方法是什么(关系数据库和非关系数据库都适合我)?

最简单的解决方案当然是为每个角色保留一个不同的表。我还找到了 this 答案,这很好,但已经有 7 年历史了,可能已经过时了。还有其他想法吗?


这是一个示例数据集:

"name": "name1"
"role": "attack"
"strength": 10
"constitution": 5

"name": "name2"
"role": "attack"
"strength": 7
"constitution": 7

"name": "name3"
"role": "defense"
"health": 8
"resistence": 8

"name": "name4"
"role": "defense"
"health": 10
"resistence": 10

"name": "name5"
"role": "support"
"mana": 4
"willpower": 3
sql oop orm polymorphism nosql
2个回答
26
投票

数据的面向对象结构

您已在

Character
群体中识别出多个类别,这些类别源自抽象角色 ,即
Attack
Defense
Support
。每种角色根据类别具有不同的属性。

所以你心里清楚有一个 OOP 设计,并希望在数据库中实现它。可以使用多种设计模式:

类或关系?

您可以考虑另一种附加模型。它是一个类似于组件的设计,基于组合(在关系的 SQL 模式中):

    您将拥有一张
  • character
     桌子,其中有 
    id
    name
    role
     
  • 您将拥有一个属性表,其中包含角色的
  • id
    property-id
    (或名称)和 
    value
如果您想要非常灵活和富有创意并发明附加属性(例如“拥有武器 A”、“拥有武器 B”、“装甲强度”等),可以建议您这样做。然而,如果你打算相对紧密地坚持当前的属性,这又有点矫枉过正了。

无 SQL

如果您想考虑非关系数据库,通常是“无 SQL 数据库”,那么您可以考虑基于文档的数据库,它非常适合处理类似于单继承表的结构。

如果您选择组件设计,那么键值存储也可以是一种选择,但您仍然需要组装各个部分。这就是额外灵活性的代价;-)

你说多态?

多态性更多的是与类相关的行为,而不是描述对象的数据。由于这里不是行为问题,我猜您的意思是处理不同类型的数据(所以更多的是关于类)。如果我在这一点上错了,请告诉我。

但是,您应该让问题中包含多态性,因为它可以帮助其他不太了解 OOP 术语的人找到类似问题的解决方案

为了扩展

0
投票
中对 NoSQL 解决方案的参考,多态数据库非常适合此类用例。这将允许您在没有 ORM 或完整性管理的情况下本机实现多态数据模型。

我已经整理了一个快速的 TypeDB

模式,应该适用于您的示例数据:

define player sub entity, abstract, owns name @key; attack-player sub player, owns strength, owns constitution; defense-player sub player, owns health, owns resistance; support-player sub player, owns mana, owns willpower; name sub attribute, value string; skill sub attribute, abstract, value long; strength sub skill; constitution sub skill; health sub skill; resistance sub skill; mana sub skill; willpower sub skill;

在这里,我定义了一个实体层次结构,每个玩家角色
attack-player

defense-player

support-player
 都扩展了抽象的 
player
 超类型。我还定义了一个属性层次结构,因此所有技能都扩展了一个抽象的 
skill
 超类型。每个玩家角色根据需要拥有不同的技能,并且他们都继承了
name
player
使用此架构,可以按如下方式插入示例数据:

insert $player-1 isa attack-player, has name "name1", has strength 10, has constitution 5; $player-2 isa attack-player, has name "name2", has strength 7, has constitution 7; $player-3 isa defense-player, has name "name3", has health 8, has resistance 8; $player-4 isa defense-player, has name "name4", has health 10, has resistance 10; $player-5 isa support-player, has name "name5", has mana 4, has willpower 3;

现在您的数据可以进行多态查询。要获得
attack

"name1"

技能,您可以使用:
match
$player isa player,
    has name "name1",
    has attack $atk;
get $atk;

要获得
"name1"
的所有技能,请使用:

match
$player isa player,
    has name "name1",
    has skill $skl;
get $skl;

要获取防守球员及其技能,请使用:
match
$player isa defense-player,
    has name $name,
    has health $hlt,
    has resistance $res;
get $name, $hlt, $res;

要获取所有拥有
mana
技能的玩家,无论其玩家角色如何,请使用:

match
$player isa player,
    has name $name,
    has mana $mna;
get $name, $mna;

要获得所有玩家及其所有技能,请使用:
match
$player isa player,
    has name $name,
    has skill $skl;
get $name, $skl;


© www.soinside.com 2019 - 2024. All rights reserved.