2016-03-11 4 views
1

Я искал для обсуждения по этому вопросу, как Google, так и Stackoverflow; «замена подстановки», «замена реализации» и т. д. не дали мне никаких результатов.Переключение реализаций интерфейса

Предположим, у нас есть интерфейс DB, а моя текущая реализация - Postgresql. Теперь я хочу обменять свою версию на MySQL. Что было бы подходящим способом сделать это? У меня есть пара идей себе:

  1. Have DB.h и DB.cpp, файл CPP, содержащий реализацию Postgresql. Теперь просто переименуем DB.cpp в DB.cpp.postgresql и реализацию MySQL до DB.cpp.
  2. Postgresql.h/Postgresql.cpp и MySQL.h/MySQL.cpp, изменение фактического заявления #include<>. Это кажется неправильным; сотни файлов могут использовать это, так что это приведет к много ненужной работе.
  3. Внесите контейнер IoC и разрешите драйвер/разъем DB оттуда.

Являются ли какие-либо из этих трех правильными, или у нас есть другой общий способ достичь этого?

+0

Вы уверены, что вам нужна только одна реализация в вашей программе? Если это так, то я не понимаю, почему сотни файлов будут включать MySQL.h вместо DB.h в первую очередь. – MikeMB

+0

1 и 2 работают над разными предположениями, извините, если я не прояснил это. 'DB.h' не существует во втором примере, в примере 2 предполагается, что у нас нет' DB.h', но файл заголовка для подключения к базе данных называется по фактическому имени драйвера :-) I ' m довольно уверен, что подход 2) является субоптимальным или просто неправильным. – Dencker

+0

Кстати, это не настоящий случай, просто псевдо-пример. – Dencker

ответ

3

(предупреждение, Неоткомпилированная код впереди)

DB.h

#include <string> 
class DB 
{ 
    public: 
    virtual bool insert(std::string content) = 0; 
    // And whatever other functions your DB interface may need ... 
} 

mysql.h

#include <DB.h> 
class MySQL : public DB 
{ 
    public 
    virtual bool insert(std::string content); 
} 

MySQL.cpp

#include <MySQL.h> 
bool MySQL::insert(std::string content) 
{ 
    // insert logic here 
    return true; 
} 

же для PostgreSQL.

createDB.cpp

#include <memory> 
#include <MySQL.h> 
#include <PostgreSQL.h> 

enum class DBType { MySQL, PostgreSQL }; 
std::unique_ptr<DB> createDB(DBType type) 
{ 
    switch(type) 
    { 
    case DBType::MySQL: 
     return std::unique_ptr<DB>{std::make_unique<MySQL(/*constructor arguments here*/)}; 
    case DBType::PostgreSQL: 
     return std::unique_ptr<DB>{std::make_unique<PostgreSQL>(/*constructor arguments here*/)}; 
    } 
} 

Это также называется Factory Pattern, если я не ошибаюсь.

+0

Это действительно фабричный шаблон; не знаю, почему я об этом не думал. Довольно хорошая идея. Благодарю. В любом случае MySQL и PostgreSQL должны иметь отдельные файлы заголовков, поэтому, наверное, я не думал об этом виде абстракции. Делает совершенный смысл.Это, в сочетании с каким-то бутстрапом, облегчит его замену, поэтому 'createDB' вызывается только в одном месте. – Dencker

+0

Также обратите внимание, что есть такие вещи, как [ODBC] (https://nl.wikipedia.org/wiki/Open_DataBase_Connectivity), которые должны абстрагировать основные данные базы данных для вас. – rubenvb

+0

Спасибо, я посмотрю. DB был просто примером для простоты, но в будущем, если мне нужно подключиться к БД, это, безусловно, пригодится, поэтому спасибо! – Dencker