Я збираюся м'яко не погодитися з усіма і сказати, що реляційний підхід тут розумний. Тут цікаво те, що предмети можуть мати кілька ролей. Основне питання полягатиме в тому, що відображення між цим реляційним макетом і макетом ОО в коді не буде відчувати себе "природним", але я думаю, що на базі даних багато ролей можна виразити чисто (без дивних кодувань або надмірностей, просто приєднується) .
Перше, що слід вирішити - це кількість даних, що є специфічними для окремих елементів, і скільки їх поділяють усі елементи даного типу.
Ось що я можу зробити, якщо всі дані є специфічними для кожного пункту:
// ITEMS table: attributes common to all items
item_id | name | owner | location | sprite_id | ...
1 | Light Saber | 14 (Tchalvek) | 381 (Tchalvek house) | 5663 | ...
// WEAPONS table: attributes for items that are weapons
item_id | damage | damage_type | durability | ...
1 | 5 | sharp | 13 | ...
// LIGHTING table: attributes for items that serve as lights
item_id | radius | brightness | duration | ...
1 | 3 meters | 50 | 8 hours | ...
У цьому дизайні кожен елемент знаходиться в таблиці елементів, а також атрибути, які мають усі (або більшість) елементів. Кожна додаткова роль, яку може зіграти предмет, - це окрема таблиця.
Якщо ви хочете використовувати його як зброю, ви шукаєте це в таблиці Зброя. Якщо він є, то він може бути використаний як зброя. Якщо його там немає, то його не можна використовувати як зброю. Наявність запису говорить про те, чи це зброя. І якщо він там, всі його атрибути, специфічні для зброї, зберігаються там. Оскільки ці атрибути зберігаються безпосередньо замість кодованої форми, ви зможете виконувати запити / фільтри з ними. (Наприклад, на сторінці показників вашої гри ви можете зібрати гравців за типом пошкодження зброї, і ви зможете це зробити з деякими приєднаннями та типом ушкодження групи.)
Елемент може мати кілька ролей і існувати у більш ніж одній специфічній для ролей таблиці (у цьому прикладі як зброя, так і освітлення).
Якщо це просто булеве на зразок "це зберігається", я б помістив його в таблицю "Елементи". Можливо, варто кешувати "це зброя" і т.д. там, щоб вам не довелося виконувати пошук на таблицях Зброя та інших ролях. Однак це додає надмірності, тому вам слід бути обережними, щоб тримати його синхронізовано.
Рекомендація Арі щодо створення додаткової таблиці для кожного типу також може використовуватися при такому підході, якщо деякі дані не змінюватимуться для кожного елемента. Наприклад, якщо пошкодження зброї не змінюються в залежності від предмета, але ролі все ще різняться для кожного елемента, ви можете розподілити атрибути спільної зброї в таблицю:
// WEAPONS table: attributes for items that are weapons
item_id | durability | weapon_type
1 | 13 | light_saber
// WEAPONTYPES table: attributes for classes of weapons
weapon_type_id | damage | damage_type
light_saber | 5 | energy
Інший підхід був би, якщо ролі, яку відіграють елементи, не відрізняються залежно від предмета, а лише за типом предмета. У такому випадку ви помістіть item_type у таблицю елементів і зможете зберігати властивості типу "зброя" та "чи зберігається вона" та "чи це світло" у таблиці ItemTypes. У цьому прикладі я також роблю назви елементів, які не змінюються для кожного елемента:
// ITEMS table: attributes per item
item_id | item_type | owner | location
1 | light_saber | 14 (Tchalvek) | 381 (Tchalvek house)
// ITEMTYPES table: attributes shared by all items of a type
item_type | name | sprite_id | is_holdable | is_weapon | is_light
light_saber | Light Saber | 5663 | true | true | true
// WEAPONTYPES table: attributes for item types that are also weapons
item_type | damage | damage_type
light_saber | 5 | energy
Цілком імовірно, що типи предметів і зброєтипи не змінюються під час гри, тому ви можете просто завантажити ці таблиці в пам'ять один раз і шукати ці атрибути в хеш-таблиці замість об'єднання з базою даних.