SOLID+DIP+фабрика
Коллеги, вопрос по интерфейсам, инверсии зависимостей, созданию экземпляров классов. Допустим, есть "клиент" (main.cpp), которому нужны некоторые данные. Клиенту не важно, как он их получит: из памяти, из файла, по сети... Он работает исключительно с интерфейсом, т.е.
dataStorage.hpp
struct Data
{
int a = 0;
int b = 0;
int c = 0;
};
// интерфейс
class DataStorage
{
public:
virtual ~DataStorage() {};
virtual Data getData() = 0;
};
main.cpp
#include <iostream>
#include "dataStorage.hpp"
using namespace std;
int main()
{
DataStorage* dataStorage;
Data data = dataStorage->getData();
cout << "a = " << data.a << '\t' << "b = " << data.b << '\t' << "c = " << data.c << '\n';
return 0;
}
Реализация интерфейса:
dataStorageImp.hpp
class DataFromMemory: public DataStorage
{
public:
DataFromMemory();
Data getData() override;
};
class DataFromFile: public DataStorage
{
public:
DataFromFile();
Data getData() override;
};
dataStorageImp.cpp
#include "dataStorageImp.hpp"
DataFromMemory::DataFromMemory() {};
Data DataFromMemory::getData()
{
Data data;
data.a = 1;
data.b = 2;
data.c = 3;
return data;
}
DataFromFile::DataFromFile() {};
Data DataFromFile::getData()
{
Data data;
data.a = 10;
data.b = 20;
data.c = 30;
return data;
}
Код не рабочий, это как бы заготовка.
Вопрос, собственно, о том, как и где я должен создать экземпляры классов-реализаций DataFromMemory и DataFomFile? Выбор между ними можно сделать по условию if "fromFile": {} или if "from_memory": {}, или используя макрос #define USE_MEMORY, или USE_FILE. Не принципиально.
Ответы (1 шт):
Я сделал следующую реализацию. Специалисты по c++ и SOLID, прокомментируйте, плз.
"main.cpp"
#define USE_DATA_FROM_MEMORY
//#define USE_DATA_FROM_FILE
#include <iostream>
#include "creator.hpp"
using namespace std;
int main()
{
Creator* creator;
DataStorage* dataStorage = creator->getInstance();
Data data = dataStorage->getData();
cout << "a = " << data.a << '\t' << "b = " << data.b << '\t' << "c = " << data.c << '\n';
delete dataStorage;
dataStorage = nullptr;
return 0;
}
"creator.hpp"
#ifndef CREATOR_HPP
#define CREATOR_HPP
#include "dataStorageImp.hpp"
class Creator
{
public:
DataStorage* getInstance()
{
#ifdef USE_DATA_FROM_MEMORY
return new DataFromMemory();
#endif // USE_DATA_FROM_MEMORY
#ifdef USE_DATA_FROM_FILE
return new DataFromFile();
#endif // USE_DATA_FROM_FILE
};
~Creator() = default;
};
#endif // CREATOR_HPP
"dataStorage.hpp"
#ifndef DATASTORAGE_HPP
#define DATASTORAGE_HPP
struct Data
{
int a = 0;
int b = 0;
int c = 0;
};
class DataStorage
{
public:
virtual Data getData() = 0;
virtual ~DataStorage() {};
};
#endif // DATASTORAGE_HPP
"dataStorageImp.hpp"
#ifndef DATASTORAGEIMP_HPP
#define DATASTORAGEIMP_HPP
#include "dataStorage.hpp"
// это просто некая реализация
class DataFromMemory: public DataStorage
{
public:
DataFromMemory() = default;
Data getData() override
{
Data data;
data.a = 1;
data.b = 2;
data.c = 3;
return data;
}
};
// другая реализация, другие значения
class DataFromFile: public DataStorage
{
public:
DataFromFile() = default;
Data getData() override
{
Data data;
data.a = 10;
data.b = 20;
data.c = 30;
return data;
}
};
#endif // DATASTORAGEIMP_HPP
Еще раз повторюсь, смысл в том, чтобы клиент (main.cpp) получал данные не зависимо от источника этих данных, исключительно через интерфейс. Вопрос чисто теоретический, понять для себя, как это можно сделать.