在 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
输入模板参数Some
(或为foo
如果将其提取为自由函数),但我不确定这是正确的方法(模板对很多人来说看起来像黑魔法,所以我更喜欢使用动态多态性)
您现在正在做的是“强制耦合”RAII 类和服务提供者类(如果您想要可测试性,它实际上应该是一个接口)。通过以下方式解决此问题:
- 抽象化
Connection
into IConnection
- 有一个单独的
ScopedConnection
除此之外还提供 RAII 的类
例如:
void Some::foo(string address, IBar& bar)
{
onBeforeConnectionCreated();
{
ScopedConnection conn(this->pFactory->getConnection());
onConnectionCreated();
bar.process(conn);
}
onConnectionClosed();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)