SOLID原則是一個有機整體 - Kislay

banq發表於2022-04-10

SOLID原則是建立一個元件間低耦合度的系統的有力工具。

首先對這些原則做一個簡單的回顧:
  • SRP:單一責任原則
  • OCP:開放封閉原則
  • Liskov替代原則
  • 介面隔離
  • 依賴性反轉


在這裡,我想談談所有的SOLID原則是如何相互聯絡的。
它們在任何情況下都同時適用;破壞一個也會破壞其他多個。
在我看來,它們應該被理解為一個連續體,而不是一套獨立的原則:一個人總是需要其中的一些原則來實現另一個(幾個)。

就個人而言,我一開始就說我不想修改現有的程式碼。誰知道我怎麼會破壞它?
我只想把我的新邏輯注入到當前執行的系統中,在我需要的特定地方。

所以SRP是我最喜歡的原則。但所有其他的原則都是為了維護這個原則。

以WindowsMachine的例子。下面是這個類,供參考。


public class WindowsMachine {
    private CPU cpu;
    private Monitor monitor;
    private KeyBoard keyboard;

    public WindowsMachine() {
        cpu = new CPU(・・・・); 
        monitor = new Monitor(...);
        keyboard = new Keyboard(..);
    
    public void startUp() {
        cpu.start();
        monitor.start();
      ....
}
}



上述程式碼表示:WindowsMachine有一個鍵盤、一個CPU和一個顯示器Monitor等子物件。(不懂”類或物件“概念的可見這個連結
在這個例子中,WindowsMachine有建立自己的子物件職責(建構函式中建立了子物件):它不僅需要知道它如何完成自己的功能,還需要知道如何建立這些子元件,這就打破了SRP。(WindowsMachine有了兩個職責,而不是一個職責,既要建立照顧組內隊員的建立,在建構函式建立隊員;還要完成自己本分的職責功能,本職工作是startup函式的功能。)

我們怎樣才能從WindowsMachine上移走構建Monitor等子元件的知識呢?
最簡單的方法是讓別人來構建Monitor物件,並在構建後把它交給WindowsMachine類(就像現實世界中發生的那樣)。
這就是依賴性倒置原則,這又是一個SOLID原則。

但是,如果任何人都可以構造一個Monitor並將其傳遞給WindowsMachine,那麼WindowsMachine就需要確保該Monitor與自身的Monitor型別相容;否則,WindowsMachine就必須處理各種型別的Monitor之間的差異。這又違反了SRP。
WindowsMachine希望其他人建立Monitor,但是所有Monitor都必須準確地做WindowsMachine所期望的事情,不管他們具體如何做到的。

我們怎樣才能做到呢?

使用Liskov替代原則,它要求子類完全這樣做。

WindowsMachine類暴露了一些介面或基類,包括Monitor的 "規格"。每個Monitor都必須完全做到這一點,而不是其他。這就保證了WindowsMachine可以被賦予任何基類Monitor的實現來工作,而WindowsMachine程式碼中沒有任何東西需要改變。

這裡我們再次看到一個原則如何支援另一個原則。

在WindowsMachine的行為受監控器的行為控制的程度上,我們已經實現了OCP,因為我們可以通過不同的Monitor實現,以不同的方式做同樣的事情。
但是,我們怎樣才能修改WindowsMachine本身的行為呢?
一種方法是開啟WindowsMachine的程式碼,在那裡新增一些條件或額外的業務邏輯來滿足我們的新要求。
但如果我們這樣做,最終在某種程度上違反了SRP,因為它現在因為多種行為原因而被改變。

為了防止這種情況,我們必須重新設計WindowsMachine元件,允許其他人對它進行子類化,並用新的行為覆蓋它。
舊的程式碼仍然適用於現有的用例,但現在可以圍繞它構建包裝器,以支援新的用例。
在這裡,OCP正在幫助維護SRP的長遠發展。

讓我們來看Monitor顯示器本身:
在孤立的情況下,它們可以有很多很多的屬性。顯示器製造商要處理大量的複雜性:但所有這些都與WindowsMachine無關。
因此,顯示器的面向WindowsMachine的部分實現了比面向製造的部分窄得多的規範集。
這就是介面隔離原則
Monito物件為兩個不同的用例實現了兩套不同的介面。(banq:也就是為不同上下文實現不同介面)

正如這個例子所顯示的,SOLID原則不能一個一個地應用。它們必須同時應用,以實現我們在系統中想要的解耦。

banq:WindowsMachine其實類似DDD中的聚合根案例,聚合根的高聚合低耦合實現可以依據此思路

相關文章