Абстрактен модул на базата данни (независим) от други модули на играта

Имам игра, която се състои от няколко модула.

Един от тях е модул база данни. Искам да го направя нещо подобно:

Database{
    public:
        save(&Object); //all my classes in the all modules inherit from Object
        load(&Object);
};

Какъв би бил най-добрият начин да направите този модул независим от други модули (други модули ще съхраняват данни в Database с помощта на save и load функции)?

Разглеждам няколко решения:

  1. Всички обекти имат нещо като serialize() метод, който е наследен от Object клас (аналогия на Java). Database използвайте този метод, за да получите низа и да го запазите. Очевидни недостатъци са: всички обекти трябва да имплементират нов метод и няма да е оптимално да се записват низове (без да се знае за структурата на класовете).
  2. Направете „манифести“ за всички класове (напр. в текстов файл, който ще бъде изпратен на Database). Тези манифести ще опишат каква е структурата на класа (напр. един низ, два двойни, един int за рядка употреба). Недостатък е гъвкавостта - промяната на класовете в други модули ще повлияе на манифестите.
  3. Всички класове имат собствени save и load методи и Database ги използват. Не го искам, защото всички класове ще трябва да знаят за типа на базата данни и save и load трябва да са в Database клас, а не разпределени в целия код (това е основна точка да се направи такъв модул).
  4. Database знае за всички други модули (и ще знае как да запази всички обекти). Лошото тук е многото зависимости. Промените в някой от модулите ще засегнат Database.

Кой път ще е добър? Или може би има по-добър вариант?


person PolGraphic    schedule 04.12.2012    source източник
comment
Когато говорите за метод serialize(), звучи така, сякаш искате да използвате хранилище за стойност на име (ала NoSQL). Обикновено базата данни ще съхранява една стойност на колона в таблица.   -  person brian beuning    schedule 05.12.2012


Отговори (1)


Едно решение, на което се натъкнах, е всички подкласове на обекти да прилагат метод virtual void serialize(ISerializer& serializer).

ISerializer ще има чисти виртуални методи като void onInt(int value), void onString(const char* string) и т.н., които да бъдат извиквани от подкласа Object в неговия serialize()-метод. Вашият модул за база данни може да имплементира ISerializer в два отделни класа, DatabaseReader и DatabaseWriter. По-късно можете да добавите ObjectInspectionFileDumper, OnScreenObjectStateDebugger или NetworkWriter, които също имплементират ISerializer, но в други модули. Всеки обект трябва само да приложи serialize()-метода веднъж, за да получи всички тези възможности за разширение.

Професионалисти:

  • Четенето и писането е доста гарантирано, че съвпадат, стига да не четете данни за стара версия на обект без някаква схема за версии отгоре.
  • Това е ортогонален дизайн, при който броят на типовете обекти и типовете сериализатор може да нараства независимо един от друг.

Минуси:

  • Главно някакви режийни виртуални функции, ако това е проблем за вашия проект. Това обаче не е нещо, което обикновено ще правите много по време на редовна игра.

По-късно може да срещнете неща, които искате да наречете Обекти, които не искате да сериализирате, тогава може да има смисъл да ги отделите в интерфейсен клас ISerializable, съдържащ само чистия виртуален serialize()- метод. За да приспособите сериализатори, където има значение (като сериализатори за отстраняване на грешки), може да искате вместо това да промените на void onInt(const char* name, int value) и т.н.

HTH

person lumor    schedule 05.12.2012