我正在用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.
}
如何将数据库连接从顶部的服务器类获取到上面伪代码底部的搜索类实例?
似乎您尝试解决的问题是一个对象依赖关系,并且使用依赖注入可以很好地解决。
您的类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 设计的核心要素是减少对象之间的耦合,以减少修改或增强应用程序部分时所需的工作量,
请查找 SO 上的依赖注入,以获取有关该 OOP 设计模式的更多信息。