Я пишу давно работающий многопоточный сервер на C ++. Он получает запросы на сокете, выполняет поиск в базе данных и возвращает ответы на сокете.
Сервер считывает различную информацию о запуске из файла конфигурации, включая параметры подключения к базе данных. Я должен использовать класс абстракции базы данных из библиотеки кода компании. Я не хочу ждать, пока попытается выполнить поиск в БД, чтобы лениво создать экземпляр подключения к БД (из-за непоказанной сложности и необходимости выхода из ошибки при запуске, если не удается установить соединение с БД).
Моя проблема в том, как передать информацию о соединении с базой данных в класс поиска, не совершая при этом никаких «уродливых» или плохих ООП-вещей, которые технически работали бы. Я хочу научиться делать это правильно.
Есть хороший шаблон дизайна для этого? Должен ли я использовать шаблон «Параметризация сверху»? Я упускаю какой-то более простой шаблон Composition?
// 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 внизу псевдокода выше?
Кажется, что проблема, которую вы пытаетесь решить, связана с зависимостью объектов и хорошо решается с помощью внедрение зависимости.
Твой класс 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
это действительно манипулирует.
Центральным элементом хорошего дизайна ООП, выделенного здесь, является уменьшение связи между объектами для уменьшения объема работы, необходимой при изменении или расширении частей приложения,
Пожалуйста, ищите для внедрение зависимости от SO для получения дополнительной информации об этом шаблоне проектирования ООП.
Других решений пока нет …