数据库模块摘要(独立于)游戏的其他模块



我有一个由几个模块组成的游戏。

其中之一是数据库模块。我想把它做成这样:

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

使该模块独立于其他模块的最佳方法是什么(其他模块将使用saveload函数在Database中存储数据)?

我考虑的解决方案很少:

  1. 所有对象都有类似serialize()的方法,它继承自Object类(类似于Java)。Database使用该方法获取并保存字符串。明显的缺点是:所有对象都必须实现新的方法,并且保存字符串不是最佳的(不知道类的结构)
  2. 为所有类制作"清单"(例如,在将发送到Database的文本文件中)。该清单将描述类的结构(例如,一个字符串、两个double、一个罕见使用int)。缺点是灵活性——更改其他模块中的类会对清单产生影响
  3. 所有类都有自己的saveload方法,Database使用它们。我不想要它,因为所有的类都必须知道数据库类型,saveload应该在Database类中,而不是分布在整个代码中(这是制作这样一个模块的要点)
  4. Database知道所有其他模块(并且知道如何保存所有对象)。糟糕的是有很多依赖关系。任何模块的更改都会影响Database

哪种方式好?或者也许还有更好的选择?

我遇到的一个解决方案是让所有Object子类实现virtual void serialize(ISerializer& serializer)方法。

ISerializer将有纯虚拟方法,如void onInt(int value)void onString(const char* string)等,由对象子类在其serialize()-方法中调用。您的数据库模块可以在两个独立的类中实现ISerializerDatabaseReaderDatabaseWriter。稍后,您可以添加ObjectInspectionFileDumperOnScreenObjectStateDebuggerNetworkWriter,它们也实现ISerializer但在其他模块中。每个对象只需要实现serialize()-方法一次,就可以获得所有扩展的可能性。

优点:

  • 只要不读取没有某种版本控制方案的旧版本对象的数据,读写就可以保证匹配
  • 这是一种正交设计,其中Object类型和Serializer类型的数量可以相互独立地增长

缺点:

  • 主要是一些虚拟函数开销,如果这对您的项目来说是个问题的话。不过,这不是你在常规游戏中通常会做的事情

稍后,您可能会遇到想要调用不想序列化的对象的东西,然后将其分离到一个ISerializable接口类中是有意义的,该接口类仅包含纯虚拟serialize()-方法。为了适应重要的序列化程序(如调试序列化程序),您可能需要改为void onInt(const char* name, int value)等。

HTH-

最新更新