В C ++ я часто использую объекты в стиле RAII, чтобы сделать код более надежным, и размещать их в стеке, чтобы сделать код более производительным (и избежать bad_alloc).
Но создание объекта конкретного класса в стеке нарушает принцип инверсии зависимостей (DI) и предотвращает насмешку над этим объектом.
Рассмотрим следующий код:
struct IInputStream
{
virtual vector<BYTE> read(size_t n) = 0;
};
class Connection : public IInputStream
{
public:
Connection(string address);
virtual vector<BYTE> read(size_t n) override;
};
struct IBar
{
virtual void process(IInputStream& stream) = 0;
};
void Some::foo(string address, IBar& bar)
{
onBeforeConnectionCreated();
{
Connection conn(address);
onConnectionCreated();
bar.process(conn);
}
onConnectionClosed();
}
IМожно протестировать IBar::process
, но я также хочу протестировать Some::foo
, не создавая настоящий объект Соединения.
Конечно, я могу использовать фабрику, но это значительно усложнит код и введет распределение кучи.
Кроме того, я не люблю добавлять метод Connection::open
, я предпочитаю создавать полностью инициализированные и полностью функциональные объекты.
Я бы сделал Connection
тип параметра шаблона для Some
(или для foo
если извлечь его как бесплатную функцию), но я не уверен, что это правильный путь (для многих шаблоны выглядят как чёрная магия, поэтому я предпочитаю использовать динамический полиморфизм)