C++ 数据库连接体系结构设计之谜

C++ 数据库连接体系结构设计之谜,c++,database,architecture,C++,Database,Architecture,我正在设计一个数据库浏览应用程序,到目前为止它还支持MySQL,但最近我也开始实现支持Sqlite,在设计连接架构的实现方式时,我遇到了一些麻烦。这只是关于“连接”部分(即:获取用户/db/host或sqlite文件名的位置),而不是数据库功能。这已经解决了 我有一个基类“Connection”,它公开“普通”方法,如name(),或纯虚拟方法,如virtualstringfulllocation()=0,它返回一个可用于标识数据库的字符串(如:database@host用于MySql,或/et

我正在设计一个数据库浏览应用程序,到目前为止它还支持MySQL,但最近我也开始实现支持Sqlite,在设计连接架构的实现方式时,我遇到了一些麻烦。这只是关于“连接”部分(即:获取用户/db/host或sqlite文件名的位置),而不是数据库功能。这已经解决了

我有一个基类“Connection”,它公开“普通”方法,如
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对象中保留相关变量,并根据这个对象的内容采取行动