【问题标题】:Design puzzle about database connectivity architecture关于数据库连接架构的设计难题
【发布时间】:2013-04-07 13:11:10
【问题描述】:

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

我有一个基类“Connection”,它公开像name() 这样的“普通”方法,或者像virtual string fullLocation() = 0 这样的纯虚方法,它返回一个可用于识别数据库的字符串(例如:@ 987654323@ 用于 MySql,或 /etc/mydb.sqlite 用于 Sqlite)。

现在,用户当然需要指定他想要连接的数据库,因此在应用程序的 GUI 中,他只需选择类型,然后填写凭据即可。我的麻烦就从这里开始了。我创建了一个MySqlConnection 和一个SqliteConnectionclasses,它们都派生自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);

而且我担心这会在整个应用程序中持续下去,因为这两个数据库引擎的性质如此不同。

您对如何以优雅的方式解决这个问题有一些指导吗?

【问题讨论】:

  • 封装变化的,封装不变的。
  • @PeterWood 正是我所做的,但在这种情况下,唯一保持不变的是连接的“名称”......即使连接方法也不同(用户/密码/主机与文件名 :) )
  • 另一种选择是拥有一个创建 Connection 对象的工厂,因此差异仅在构造过程中相关
  • @fritzone 所以...封装它 (c:

标签: c++ database architecture


【解决方案1】:

更优雅的方式是设计一个工厂类并在该工厂的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 输入更新它的实例,并将这个对象交给连接工厂的连接生成方法。

【讨论】:

  • 我宁愿不让工厂知道 GUI,因为我现在使用 Qt,如果我决定切换到 GTK,我会在“核心”中拥有这种依赖...跨度>
  • @fritzone 然后可以将相关变量保存在一个struct对象中,根据这个对象的内容采取行动
【解决方案2】:

您需要模式工厂,它将以抽象的方式为您创建连接。是肤浅的回答。 这个工厂将是很好的 Builder 模式的参数化。类似的东西:

 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);

【讨论】:

    猜你喜欢
    • 2011-03-14
    • 2015-08-29
    • 2020-09-20
    • 1970-01-01
    • 1970-01-01
    • 2011-10-26
    • 1970-01-01
    相关资源
    最近更新 更多