C++中的Inversion of Control和Dependency injection有什么区别?
我最近一直在阅读关于DI和IoC的C++。我有点困惑(即使在阅读SO的相关问题之后),并希望有所澄清。C++中的Inversion of Control和Dependency injection有什么区别?
在我看来,熟悉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;
};
这是(即,使用迭代器,而不是访问集合本身)的依赖注入?控制反转?都不是?
我们来看另一个例子。我们有一个班级:
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_;
};
这似乎是依赖注入。但它是否反转控制?
另外,如果我失去了一些东西,有人可以帮我吗?这似乎是做事的自然方式,所以如果这就是依赖注入,那为什么人们很难使用它?
Inversion of Control是一个非常通用的概念,具有不同的含义,取决于您所谈论的“控制”的种类。依赖注入是一种特定的形式。
逆控制的和迭代
在这种情况下“控制”是指“流控制”。
我认为你的第一个涉及迭代的例子并不是真正的控制反转,因为那个代码明确地执行了流控制。控制倒置会将要执行的操作与流量控制分开。这可能是这样的(请原谅我的Java/C#):
SumVisitor sumVisitor = new SumVisitor();
collection.AcceptVisitor(sumVisitor);
int sum = sumVisitor.GetSum();
参观者对象做了它访问的每个集合元素,例如更新总计计数器字段。但它没有控制在何时或何时被集合调用,因此控制反转。您也可以实施MedianVisitor
,MeanVisitor
,MaximumVisitor
等等。每一个都使用Visit(Element)
方法实现通用的IVisitor
接口。
对于收集来说,情况正好相反:它不知道访问者的作用,通过为集合中的每个元素调用visitor.Visit(element)
来简单地管理流量控制。不同的访问者实现对于集合而言都是相同的。控制的
反演和对象图结构
在这种情况下的“控制”是指“在如何组件创建和有线一起控制”。
在任何非平凡的应用程序中,代码被拆分成必须协作的组件。为了保持组件的可重用性,它们不能直接创建对方,因为它们会永久地将它们粘合在一起。取而代之的是,单个部件放弃控制过构造和部件布线。
Dependency injection是通过引用构造函数中的协作者对象来实现此目的的一种方法。然后,您需要一个单独的启动代码,其中创建所有组件并将它们连接在一起,或者需要一个依赖注入框架来为您提供帮助。你的Dice类实际上是一个依赖注入的例子。
另一种放弃对象图构造控制的方法是Service Locator模式,虽然它有disadvantages。
让我试着回答。
你的第一个例子既不是。它只是一个模板。
因为它是依赖注入,所以必须选择一个IMPLEMENTATION并将其提供给模板。
对于IoC,模板必须在运行时(不是编译时)提供给IMPLEMENTATION类型,并用作“mean()”函数的实现(想象一下提供均值功能实现)
你的第二个例子看起来像DI/IoC的消费者。将Engine的实现发送到您的类中的代码将是DI/IoC组件。
希望这是准确的,并有帮助。
你读过维基了吗?它有一个非常明确的定义IoC/DI http://en.wikipedia.org/wiki/Inversion_of_control – CDSO1 2010-04-15 20:09:25
在C++中,我们不做IoC或DI - 我们有我们自己的自命不凡和严重命名的概念。 – 2010-04-15 20:18:04
如果你不小心,你的模板函数可能会被零分。 – 2010-04-15 20:20:37