В 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();
}
Я могу протестировать IBar :: process
, но я также хочу протестировать Some :: foo
, не создавая реального объекта Connection.
Конечно, я могу использовать фабрику, но это значительно усложнит код и представит динамическое распределение.
Кроме того, мне не нравится добавлять метод Connection :: open
, я предпочитаю создавать полностью инициализированные и полностью функциональные объекты.
Я бы сделал Connection
type параметром шаблона для Some
(или для foo
, если извлекать его как бесплатную функцию), но я не уверен что это правильно (шаблоны для многих кажутся черной магией, поэтому я предпочитаю использовать динамический полиморфизм)