【问题标题】:OOP: proper class design for database connection in derived child class?OOP:派生子类中数据库连接的正确类设计?
【发布时间】:2013-01-31 00:59:24
【问题描述】:

我正在用 C++ 编写一个长时间运行的多线程服务器。它在套接字上接收请求,进行数据库查找并在套接字上返回响应。

服务器从配置文件中读取各种运行信息,包括数据库连接参数。我必须使用公司代码库中的数据库抽象类。我不想等到尝试进行数据库搜索以延迟实例化数据库连接(由于未显示复杂性以及如果无法建立数据库连接,则需要在启动时出错退出)。

我的问题是如何将数据库连接信息放到搜索类中,而不需要做任何技术上可行的“丑陋”或糟糕的 OOP 事情。我想学习如何正确地做到这一点。

有没有很好的设计模式来做这件事?我应该使用“从上方参数化”模式吗?我错过了一些更简单的组合模式吗?

    // Read config file.
    // Open DB connection using config values.

    Server::process_request(string request, string response) {
        try {
            Process process(request);
            if (process.do_parse(response)) {
                return REQ_OK;
            } else {
                // handle error
            }
        } catch (..,) {
            // handle exceptions
        }
    }

    class Process : public GenericRequest {
    public:
        Process(string *input) : generic_process(input) {};
        bool    do_parse(string &output);
    }

    bool Process::do_parse(string &output) {
        // Parse the input request.
        Search search;      // database search object
        search.init( search parameters from parsing above );

        output = format_response(search.get_results());
    }

    class Search {
        // must use the Database library connection handle.
    }

如何将数据库连接从顶部的 Server 类获取到上面伪代码底部的 Search 类实例?

【问题讨论】:

  • 你应该展示你拥有的当前类层次结构,也许还有一些更相关的方法。但不要显示方法实现,因为它们与面向对象的设计无关。
  • 您的服务器是应用程序中的单例吗?
  • @user1610015 实际上了解每种方法的目的是很有用的,并且显示一些突出显示方法要点的代码很好地服务于该目的,恕我直言。
  • @didierc 是的,它是执行此功能的多个服务器中唯一的一个,这是线程化的原因之一。

标签: c++ oop design-patterns database-connection parameterization


【解决方案1】:

看来您要解决的问题是对象依赖性之一,使用dependency injection 可以很好地解决。

您的课程Process 需要Search 的实例,必须以某种方式对其进行配置。与其让Process 的实例分配他们自己的Search 实例,不如让他们在构建时收到一个现成的实例会更容易。 Process 类不必知道Search 的配置细节,因此避免了不必要的依赖。

但随后问题级联到必须创建Process 的任何对象,因为现在这个对象必须知道配置细节!在您的情况下,这并不是真正的问题,因为 Server 类是创建 Process 实例的类,并且它恰好知道 Search 的配置详细信息。

但是,更好的解决方案是实现一个专门的类 - 例如DBService,它将封装从配置步骤获取的数据库详细信息,并提供一种方法来准备好Search 实例。使用此设置,没有其他对象将依赖 Search 类的构造和配置。作为一个额外的好处,您可以轻松实现和注入一个DBService 模型对象,这将帮助您构建测试用例。

class DBSearch {
    /* implement/extends the Search interface/class wrt DB */
};

class DBService {
    /* constructor reads up configuration details somehow: command line, file */

     Search *newSearch(){
         return new DBSearch(config); // search object specialized on db
     }

};

上面的代码在一定程度上说明了解决方案。请注意,newSearch 方法不限于仅构建 Search 实例,而是可以构建任何专门用于该类的对象(例如上面的类 DBSearch)。对Process的依赖几乎已经去掉了,现在只需要知道它真正操作的Search的接口。

此处强调的良好 OOP 设计的核心要素是减少对象之间的耦合,以减少修改或增强应用程序部分时所需的工作量,

请查找 dependency injection on SO 以获取有关该 OOP 设计模式的更多信息。

【讨论】:

  • 因此在您的示例中,DBService 可以提供一个名为 newSearch() 的方法,该方法将向任何调用者返回一个完整的 Search 对象,包括 Process 的实例,对吗?听起来简单干净,正是我所需要的。
猜你喜欢
  • 2015-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-24
  • 2018-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多