2015-02-24 96 views
3

我學習它周圍(如SOLID依賴倒置原則特別)設計模式和東西,它看起來像我失去的東西:依賴倒置原則:試圖瞭解

DIP規則我應該能夠通過不在類中創建一個對象(組合),但發送對象引用/指針到類構造函數(聚合)使類更脆弱。但這意味着我必須在其他地方創建一個實例:所以聚合越靈活,另一個越脆弱。

請解釋我在哪裏錯了。

回答

5

你只需要遵循這個想法,直到它的邏輯結論。是的,你必須在其他地方創建實例,但是這可能不僅僅是在你的類的上一級的類中,它還需要被推出,直到只在應用程序的最外層創建對象。

理想情況下,您可以在一個地方創建所有對象,這稱爲composition root(例外情況是從工廠創建的對象,但工廠是在組合根中創建的)。具體取決於您正在構建的應用程序的類型。

  • 在桌面應用程序,這將是在主方法(或非常接近)
  • 在ASP.NET(包括MVC)應用,這將是在Global.asax中
  • 在WCF,這將是在ServiceHostFactory

這個地方可能最終會被「脆弱」,但你只能在一個地方改變的事情,爲了能夠重新配置您的應用程序,然後所有其他類都是可測試和配置的urable。

this excellent answer(這是上面引述的)

0

是的,你需要在某個地方實例化類。如果你正確地遵循DIP,你將最終在一個地方創建所有的實例。我把這個地方稱爲課堂作文。閱讀我的博客,瞭解更多關於此主題的深入瞭解Here

0

您錯過的一個重要可能性是注入工廠,而不是課程本身。這樣做的一個好處是它可以讓你對實例的所有權變得更加清潔。注意代碼有點醜,因爲我明確地給出了組件的容器所有權。如果你使用shared_ptr而不是unique_ptr,那麼事情可能會有點整潔,但是所有權是不明確的。

所以開始的代碼看起來像這樣:

struct MyContainer { 
    std::unique_ptr<IFoo> foo; 
    MyContainer() : foo(new Foo()) {}; 
    void doit() { foo->doit(); } 
} 

void useContainer() { 
    MyContainer container; 
    container.doit(); 
} 

非出廠版本是這樣的

struct MyContainer { 
    std::unique_ptr<IFoo> foo; 
    template<typename T> 
    explicit MyContainer(std::unique_ptr<T> && f) : 
    foo(std::move(f)) 
    {} 
    void doit() { foo->doit(); } 
} 

void useContainer() { 
    std::unique_ptr<Foo> foo(new Foo()); 
    MyContainer container(std::move(foo)); 
    container.doit(); 
} 

出廠版本會是什麼樣子

struct FooFactory : public IFooFactory { 
    std::unique_ptr<IFoo> createFoo() override { 
    return std::make_unique<Foo>(); 
    } 
}; 

struct MyContainer { 
    std::unique_ptr<IFoo> foo; 
    MyContainer(IFooFactory & factory) : foo(factory.createFoo()) {}; 
    void doit() { foo->doit(); } 
} 

void useContainer() { 
    FooFactory fooFactory; 
    MyContainer container(fooFactory); 
    container.doit(); 
} 

IMO明確所有權在C++中的生命週期很重要 - 其一個C++身份的關鍵部分 - 它是RAII和許多其他C++模式的核心。