依賴反轉原理,IoC容器和依賴注入:第1部分

目錄

介紹

先決條件

依賴倒置原則(DIP)

總結


介紹

在處理WPF應用程序時,我遇到過諸如Unity容器,IoC,依賴注入之類的術語。當時,我很迷茫,想着這一切的需要。但後來,當我逐漸瞭解到它的好處時,我意識到它的實際需要。

在本文中,我將嘗試解釋DIIoC的需求和用法。基本上,本文分爲五個部分:

  • 第1部分:依賴反轉原理(當前正在閱讀)
  • 第2部分:控制反轉和IoC容器
  • 第3部分:自定義IoC容器
  • 第4部分:具有生命週期選項的自定義IoC容器
  • 第5部分:使用Microsoft Unity的依賴項注入(DI)

本文的這一部分是關於依賴倒置原理的。希望您會發現本文易於理解和實現。

先決條件

最好對以下項一無所知:

  • 開閉原則
  • 接口隔離原理

依賴倒置原則(DIP

DIPSOLID原則之一,由Robert Martin C.先生在1992年提出。

根據羅伯特·馬丁(C. Robert Martin)的依賴倒置原則:

  1. 高級模塊不應依賴於低級模塊。兩者都應依賴抽象。
  2. 抽象不應依賴細節。細節應依賴於抽象。

DIP是指將常規依賴性從高級模塊轉換爲低級模塊。

Bob Martin Peper期刊的示例:

在圖1中,一個複製程序(高級模塊)從鍵盤讀取並寫入打印機。這裏的複製程序取決於Read KeyboardWrite Printer並緊密耦合

public class Copy
{
    public void DoWork()
    {
        ReadKeyboard reader = new ReadKeyboard();
        WritePrinter writer = new WritePrinter();

        string data = reader.ReadFromKeyboard();
        writer.WriteToPrinter(data);
    }
}

在我們要求向程序中添加更多讀取器或寫入器之前,此實現似乎非常好。在這種情況下,我們需要更改複製程序以適應新的讀者和作家,並且需要編寫條件語句,該條件語句將根據用途選擇讀者和作家,這違反了面向對象設計的打開/關閉原理。

例如,我們要擴展複印程序(參見圖1.b),該程序也可以從掃描儀讀取並寫入閃存盤。在這種情況下,我們需要修改複製程序:

public class Copy
{
    public void DoWork()
    {
        string data;
        switch (readerType)
        {
            case  "keyboard":
                ReadKeyboard reader = new ReadKeyboard();
                data = reader.ReadFromKeyboard();
                break;
            case "scanner":
                ReadScanner reader2 = new ReadScanner();
                data = reader2.ReadFromScanner();
                break;
        }
        switch (writerType)
        {
            case "printer":
                WritePrinter writer = new WritePrinter();
                writer.WriteToPrinter(data);
                break;
            case "flashdisk":
                WriteFlashDisk writer2 = new WriteFlashDisk();
                writer2.WriteToFlashDisk(data);
                break;
        }
    }
}

同樣,如果您繼續添加更多讀取器或寫入器,則我們需要更改複製程序的實現,因爲複製程序取決於讀取器和寫入器的實現。

爲了解決這個問題,我們可以修改copy程序,使其依賴於抽象而不是依賴於實現。下圖說明了反轉依賴關係。

在上圖中,Copy程序依賴於兩個抽象,IReaderIWriter執行。只要底層組件能夠對抽象進行確認,copy程序就可以從這些組件中讀取內容。

例如,在上圖中,ReadKeyboard實現IReader接口和WritePrinter實現IWriter,因此使用IReaderIWriter接口複製程序可以執行復制操作。因此,如果我們需要添加更多低級組件(如掃描儀和閃存盤),則可以通過從掃描儀和閃存盤來實現。以下代碼說明了這種情況:

public interface IReader
{
    string Read();
}

public interface IWriter
{
    void Write(string data);
}

public class ReadKeyboard : IReader
{
    public string Read()
    {
        // code to read from keyboard and return as string
    }
}

public class ReadScanner : IReader
{
    public string Read()
    {
        // code to read from scanner and return as string
    }
}

public class WritePrinter : IWriter
{
    public void Write(string data)
    {
        // code to write to the printer
    }
}

public class WriteFlashDisk : IWriter
{
    public void Write(string data)
    {
        // code to write to the flash disk
    }
}

public class Copy
{
    private string _readerType;
    private string _writerType;

    public Copy(string readerType, string writerType)
    {
        _readerType = readerType;
        _writerType = writerType;
    }

    public void DoWork()
    {
        IReader reader;
        IWriter writer;
        string data;
        switch (readerType)
        {
            case  "keyboard":
                reader = new ReadKeyboard();
                break;
            case "scanner":
                reader = new ReadScanner();
                break;
        }

        switch (writerType)
        {
            case "printer":
                writer = new WritePrinter();
                break;
            case "flashdisk":
                writer = new WriteFlashDisk();
                break;
        }

        data = reader.Read();
        writer.Write(data);
    }
}

在這種情況下,細節依賴於抽象,但高級類仍依賴於低級模塊。在實例化高級模塊範圍內的低級模塊對象時,高級模塊仍然需要在添加新的低級組件時進行修改,這不能完全滿足DIP

爲了刪除依賴關係,我們需要在高級模塊之外創建依賴關係對象(低級組件),並且應該有某種機制將該依賴關係對象傳遞給依賴模塊。

現在出現了一個新問題,即如何實現依賴倒置。

上述問題的答案之一可以是控制反轉(IoC)。考慮以下代碼段:

public class Copy
{
    public void DoWork()
    {
        IReader reader = serviceLocator.GetReader();
        IWriter writer = serviceLocator.GetWriter();
        string data = reader.Read();
        writer.Write(data);
    }
}

高亮顯示的代碼替換了實例化讀取器和寫入器對象的邏輯。在這裏,我們將控件創建從Copy程序(高級模塊)轉換爲服務定位器。因此,copy無需通過添加/刪除低級模塊來更改程序。

依賴注入是實現IoC的機制之一。在本文的下一部分中,我將介紹什麼是控制反轉(IoC),以及使用不同機制(依賴注入(DI)是實現之一)實現依賴反轉原理的方法。

總結

在本文的這一部分中,我已經解釋了依賴性反轉原理(DIP)及其在實時場景中的需求。

在本文的後面,我將解釋控制反轉(IoC)和依賴注入(DI)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章