rlb*_*ond 13 c++ dependency-injection inversion-of-control
我最近一直在阅读关于C++中DI和IoC的内容.我有点困惑(即使在此处阅读相关问题后),并希望得到一些澄清.
在我看来,熟悉STL和Boost导致使用依赖注入相当多.例如,假设我创建了一个函数,它找到了一系列数字的平均值:
template <typename Iter>
double mean(Iter first, Iter last)
{
double sum = 0;
size_t number = 0;
while (first != last)
{
sum += *(first++);
++number;
}
return sum/number;
};
Run Code Online (Sandbox Code Playgroud)
这是(即使用迭代器而不是访问集合本身)依赖注入?控制倒置?都不是?
让我们看另一个例子.我们有一节课:
class Dice
{
public:
typedef boost::mt19937 Engine;
Dice(int num_dice, Engine& rng) : n_(num_dice), eng_(rng) {}
int roll()
{
int sum = 0;
for (int i = 0; i < num_dice; ++i)
sum += boost::uniform_int<>(1,6)(eng_);
return sum;
}
private:
Engine& eng_;
int n_;
};
Run Code Online (Sandbox Code Playgroud)
这似乎是依赖注入.但是控制倒置了吗?
另外,如果我遗失了某些东西,有人可以帮助我吗?这似乎是做事的自然方式,所以如果这就是依赖注入,为什么人们很难使用它呢?
Wim*_*nen 17
控制反转是一个非常通用的概念,具有不同的含义,取决于您所谈论的"控制"类型.依赖注入是一种特定的形式.
控制和迭代的反转
在这种情况下,"控制"意味着"流量控制".
我认为你的第一个涉及迭代的例子并不是真正的控制反转,因为该代码明确地执行了流控制.控制反转将将要执行的动作与流控制分开.它可能看起来像这样(原谅我的java/C#):
SumVisitor sumVisitor = new SumVisitor();
collection.AcceptVisitor(sumVisitor);
int sum = sumVisitor.GetSum();
Run Code Online (Sandbox Code Playgroud)
访问者对象为其访问的每个集合元素执行某些操作,例如更新和计数器字段.但它无法控制集合如何或何时调用它,因此控制反转.你也可以实现MedianVisitor,MeanVisitor,MaximumVisitor,等等.每个都IVisitor使用Visit(Element)方法实现通用接口 .
对于集合,情况正好相反:它不了解访问者的行为,只需通过调用visitor.Visit(element)集合中的每个元素来处理流控制.不同的访客实现对于集合看起来都是一样的.
控制反演和对象图构造
在这种情况下,"控制"意味着"控制组件如何创建和连接在一起".
在任何非平凡的应用程序中,代码都被分成必须协作的组件.为了使组件可重复使用,它们不能直接相互创建,因为它们会永久地将它们粘合在一起.相反,各个组件放弃了对结构和组件布线的控制.
依赖注入是实现此目的的一种方法,方法是在构造函数中引用协作者对象.那么你需要的启动代码的单独部件,所有的部件创建并连接在一起,或依赖注入框架,需要照顾这对你.你的Dice类确实是依赖注入的一个例子.
放弃对象图构造控制的另一种方法是服务定位器模式,尽管它有其缺点.