2010-04-15 115 views
10

我最近一直在閱讀關於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_; 
}; 

這似乎是依賴注入。但它是否反轉控制?

另外,如果我失去了一些東西,有人可以幫我嗎?這似乎是做事的自然方式,所以如果這就是依賴注入,那爲什麼人們很難使用它?

+1

你讀過維基了嗎?它有一個非常明確的定義IoC/DI http://en.wikipedia.org/wiki/Inversion_of_control – CDSO1 2010-04-15 20:09:25

+6

在C++中,我們不做IoC或DI - 我們有我們自己的自命不凡和嚴重命名的概念。 – 2010-04-15 20:18:04

+0

如果你不小心,你的模板函數可能會被零分。 – 2010-04-15 20:20:37

回答

14

Inversion of Control是一個非常通用的概念,具有不同的含義,取決於您所談論的「控制」的種類。依賴注入是一種特定的形式。

逆控制的和迭代

在這種情況下「控制」是指「流控制」。

我認爲你的第一個涉及迭代的例子並不是真正的控制反轉,因爲那個代碼明確地執行了流控制。控制倒置會將要執行的操作與流量控制分開。這可能是這樣的(請原諒我的Java/C#):

SumVisitor sumVisitor = new SumVisitor(); 
collection.AcceptVisitor(sumVisitor); 
int sum = sumVisitor.GetSum(); 

參觀者對象做了它訪問的每個集合元素,例如更新總計計數器字段。但它沒有控制在何時或何時被集合調用,因此控制反轉。您也可以實施MedianVisitorMeanVisitor,MaximumVisitor等等。每一個都使用Visit(Element)方法實現通用的IVisitor接口。

對於收集來說,情況正好相反:它不知道訪問者的作用,通過爲集合中的每個元素調用visitor.Visit(element)來簡單地管理流量控制。不同的訪問者實現對於集合而言都是相同的。控制的

反演和對象圖結構

在這種情況下的「控制」是指「在如何組件創建和有線一起控制」。

在任何非平凡的應用程序中,代碼被拆分成必須協作的組件。爲了保持組件的可重用性,它們不能直接創建對方,因爲它們會永久地將它們粘合在一起。取而代之的是,單個部件放棄控制過構造和部件佈線。

Dependency injection是通過引用構造函數中的協作者對象來實現此目的的一種方法。然後,您需要一個單獨的啓動代碼,其中創建所有組件並將它們連接在一起,或者需要一個依賴注入框架來爲您提供幫助。你的Dice類實際上是一個依賴注入的例子。

另一種放棄對象圖構造控制的方法是Service Locator模式,雖然它有disadvantages

1

讓我試着回答。

你的第一個例子既不是。它只是一個模板。

因爲它是依賴注入,所以必須選擇一個IMPLEMENTATION並將其提供給模板。

對於IoC,模板必須在運行時(不是編譯時)提供給IMPLEMENTATION類型,並用作「mean()」函數的實現(想象一下提供均值功能實現)

你的第二個例子看起來像DI/IoC的消費者。將Engine的實現發送到您的類中的代碼將是DI/IoC組件。

希望這是準確的,並有幫助。

相關問題