我的应用程序处理不同类型的消息并将它们存储在数据库中。现在我使用了以下设计:
数据库类:
class DbObject
{
public:
// read/write object members from/to DB
virtual void readFromDb() = 0;
virtual void writeToDb() = 0;
// Other stuff, db connection etc.
void doDbStuff();
}
消息的基类:
class BaseMsg
{
public:
// read/write object members from/to DB
virtual std::string toXml() = 0;
virtual void fromXml(const & std::string s) = 0;
}
消息类型A,B等。
class MsgA : public BaseMsg, DbObject
{
public:
std::string toXml();
void fromXml(const & std::string s);
void readFromDb();
void writeToDb();
}
这个设计运行良好,每个处理过的消息都有它自己的对象,可以写入XML,从XML读取,存储和读取数据库中的消息特定的东西(在MsgA中实现)。
但是,目前我们正在考虑将应用程序移植到当前数据库不可用的新平台,因此我们将使用其他数据库类型。
通常我现在有一个用于数据库访问的基类和每种数据库类型的子类。但是目前的设计是不可能的,因为我不想拥有MsgADatabase1类和MsgADatabase2类等。
是否有任何设计模式,我原则上可以保留当前的设计,但是隐藏当前使用的数据库类型在某种抽象层后面?
答案 0 :(得分:3)
<强> 1。首先想到的是DbOject
作为适配器。
根据Gang of Four的说法, adapter 将通过多重继承或组合为适配对象(具体数据库对象)提供目标接口。
在多重继承的上下文中,此设计会强制对于您在消息中继承的每个DbObject
,其构造函数将创建与DB特定对象的一对一链接。但构造函数如何才能知道要创建的具体db类?
<强> 2。接下来想一想:将此适配器与抽象工厂
结合使用创建实例化抽象数据库独立对象的具体数据库相关对象的最自然模式是使用 abstract factory 。
结合适配器,您将拥有以下方案:
Database
)对象使用具体的数据库相关工厂(class DatabaseBrandA : public Database
)进行实例化DbIndependentObject
的功能。具体工厂实现此功能,提供自己的具体对象(class DbBrandAdependentObject : public DbIndependentObject
)DbObject
适配器都会请求虚拟工厂实例化新对象。因此,它指的是由DbIndependentObject
)DbBrandAdependentObject
但是,我不知道您的DbObject
的内容是否真的如此丰富,以至于它需要与数据库特定对象的一对一关系。这种复杂的模式在这里不是一种矫枉过正吗?
3.最终结论:适配器与代理设计模式相结合
我怀疑你的DbObject
只是一种方便的方式来获取派生消息对象实现的虚拟读写函数,只要需要数据库交互就可以调用它们。
如果您的当前代码的设计使DbOject
封装了与数据库相关的所有内容,那么您只需要 proxy 到此数据库。
根据以下情况,这将有效:
Database
)对象通过具体数据库实例化(class DatabaseBrandA : public Database
)DbObject
将充当引用数据库对象的代理。 DbObject
通过提供所需的读写功能充当消息的适配器。 答案 1 :(得分:2)
您可以实现适配器模式并将数据源(任何数据库或其他数据源)保留为外部实体,以减少耦合。