C++ 数据库连接体系结构设计之谜
我正在设计一个数据库浏览应用程序,到目前为止它还支持MySQL,但最近我也开始实现支持Sqlite,在设计连接架构的实现方式时,我遇到了一些麻烦。这只是关于“连接”部分(即:获取用户/db/host或sqlite文件名的位置),而不是数据库功能。这已经解决了 我有一个基类“Connection”,它公开“普通”方法,如C++ 数据库连接体系结构设计之谜,c++,database,architecture,C++,Database,Architecture,我正在设计一个数据库浏览应用程序,到目前为止它还支持MySQL,但最近我也开始实现支持Sqlite,在设计连接架构的实现方式时,我遇到了一些麻烦。这只是关于“连接”部分(即:获取用户/db/host或sqlite文件名的位置),而不是数据库功能。这已经解决了 我有一个基类“Connection”,它公开“普通”方法,如name(),或纯虚拟方法,如virtualstringfulllocation()=0,它返回一个可用于标识数据库的字符串(如:database@host用于MySql,或/et
name()
,或纯虚拟方法,如virtualstringfulllocation()=0
,它返回一个可用于标识数据库的字符串(如:database@host
用于MySql,或/etc/mydb.sqlite
用于sqlite)
现在,用户当然需要指定要连接的数据库,因此在应用程序的GUI中,用户只需选择类型,然后填写凭据。我的麻烦就从这里开始。我创建了一个MySqlConnection
和一个SqliteConnection
类,这两个类都是从Connection
派生出来的,但大多数情况下,我最终会得到如下结果:
Connection* c = 0;
if(gui->engine_name() == "MYSQL")
{
string host = gui->getHost();
string user = gui->getUser();
string password = gui->getPassword();
int port = gui->getPort();
string db = gui->getDatabase();
c = new MySqlConnection(host, user, password, db, port);
}
else
{
string dbFile = gui->getSqliteDbFile();
c = new SqliteConnection(dbFile);
}
string meta = application->use_connection(&c);
我担心,由于这两个数据库引擎的性质如此不同,这将在整个应用程序中持续下去
对于如何以优雅的方式解决这个问题,您有一些指导吗?更优雅的方式是设计一个工厂类,并在该工厂的
GenerateConnection()
方法中处理GUI输入:
void ConnectionFactory::GenerateConnection(Connection* c)
{
if(gui->engine_name() == "MYSQL")
{
string host = gui->getHost();
string user = gui->getUser();
string password = gui->getPassword();
int port = gui->getPort();
string db = gui->getDatabase();
c = new MySqlConnection(host, user, password, db, port);
}
else
{
string dbFile = gui->getSqliteDbFile();
c = new SqliteConnection(dbFile);
}
}
如果您不喜欢依赖gui,您可以定义一个名为Parameters的结构,并根据gui输入更新其实例,并将此对象提供给connection factory的连接生成方法。您需要pattern factory,它将以抽象的方式为您创建连接。这是肤浅的回答。 这个工厂将是一个很好的参数化与建设者模式。诸如此类:
ParamBuilder *b = new ParamBuilder;
if(gui->engine_name() == "MYSQL")
{
b->setHost(gui->getHost())
->setUser(gui->getUser());
->setPassword(gui->getPassword());
...
}
else
{
b->setFile(gui->getSqliteDbFile());
}
Connection *c = globalConnectionFactory->createConnection(b);
封装变化的内容,封装保持不变的内容。@PeterWood这正是我所做的,但在本例中,唯一保持不变的是连接的“名称”。。。即使连接方法不同(user/pass/host与filename:)),另一个选择是使用工厂创建
连接
对象,因此差异仅在construction@fritzone所以封装(c:我不想让工厂知道GUI,因为我现在使用的是Qt,如果我决定切换到GTK,我会在“core”中有这个依赖项…@fritzone,那么你可以在struct对象中保留相关变量,并根据这个对象的内容采取行动