首頁  >  文章  >  Java  >  堅實的原則

堅實的原則

Linda Hamilton
Linda Hamilton原創
2024-10-21 06:12:02975瀏覽

SOLID Principles

SOLID 是一組基本原則,旨在增強物件導向程式設計 (OOP) 中程式碼的可管理性和可擴展性。它由五個關鍵原則組成:

  1. S單一責任原則 — SRP
  2. O筆閉原則 — OCP
  3. L伊斯科夫替代原理 — LSP
  4. I介面隔離原則 — ISP
  5. D 依存倒置原理 — DIP

這些原則是由 Robert C. Martin(也稱為 Uncle Bob)在 2000 年代初期提出的,此後已在軟體開發社群中廣泛採用。透過遵循 SOLID 原則,開發人員可以創建更易於理解、修改和擴展的程式碼,從而形成更強壯和可維護的軟體系統。

單一職責原則(SRP)

單一職責原則是 OOP 和 SOLID 中第一個也是最基本的原則。顧名思義,這原則的意思是「一個類別應該只負責一個特定的責任」。

假設我們有一個名為 Invoice 的類,其中包含 2 個方法generateInvoice() 和 saveToFiles() 。

public class Invoice {
  private Long InvoiceNo;

  public void generateInvoice() {
    // code to generate Invoice.
  }

  public void saveToFiles() {
    // code to save invoice as a file.
  }
}

這不是一個好的做法,因為 Invoice 類別有兩個職責。更好的方法是將這些功能分成專用的類別。

public class Invoice {
  private Long InvoiceNo;

  public void generateInvoice() {
    // code to generate Invoice.
  }
}

public class FileManager {
  public void saveToFiles(Invoice invoice) {
    // code to save invoice as a file.
  }
}

在這裡,我們可以看到我們有 2 個用於用例的類別:

  • 產生發票
  • 儲存到檔案

遵循 SRP 的好處

  • 改進的程式碼組織:透過將關注點分成不同的類,程式碼庫變得更有組織性並且更容易導航。
  • 更好的可維護性:當一個類別具有單一職責時,更容易理解其目的並進行更改,而不會產生意想不到的副作用。
  • 提高可重用性:具有單一職責的類別更有可能在應用程式的不同部分甚至其他項目中重複使用。
  • 更容易測試:具有單一職責的類別通常更小、更集中,使它們更容易單獨測試。

開閉原則(OCP)

開閉原則是SOLID的另一個核心原則。此原則由 Bertrand Meyer 於 1997 年提出。這個原則背後的想法是「軟體工件(類別、模組和函數)應該對擴展開放,但對修改關閉。」

例如;

比方說,我們有一個名為 Shape 的類,我們可以用這個類來計算形狀的面積。

public class Invoice {
  private Long InvoiceNo;

  public void generateInvoice() {
    // code to generate Invoice.
  }

  public void saveToFiles() {
    // code to save invoice as a file.
  }
}

在上面的程式碼中,新增形狀需要修改現有的 Shape 類,這不是一個好的做法。

以下是一個程式碼範例,示範如何將開閉原則應用於此場景。

public class Invoice {
  private Long InvoiceNo;

  public void generateInvoice() {
    // code to generate Invoice.
  }
}

public class FileManager {
  public void saveToFiles(Invoice invoice) {
    // code to save invoice as a file.
  }
}

透過OCP的應用,我們可以在不修改目前實現的情況下添加許多我們想要的形狀。

注意:使用介面並不是實現 OCP 的唯一方法。

遵循 OCP 的好處

  • 降低錯誤風險:透過不修改現有程式碼,可以最大限度地降低引入新錯誤或破壞現有功能的風險。
  • 提高可維護性:遵循 OCP 的程式碼更容易維護和擴展,因為可以在不更改現有程式碼庫的情況下添加新功能。
  • 增強靈活性:抽象和多態性的使用允許更靈活和適應性更強的設計,從而更容易適應不斷變化的需求。

里氏替換原理 (LSP)

里氏替換原則是 OOP 中的另一個重要原則。它是由 Barbara Liskov 於 1987 年在一次關於資料抽象的會議演講中引入的。

該原則指出,「超類別的物件應該可以用其子類別的物件替換,而不改變程式的正確性」。

例如,如果 Circle 和 Rectangle 是 Shape 的子類型,那麼我們應該能夠用 Circle 或 Rectangle 物件取代 Shape 對象,不會有任何問題。

public class Shape {
    private String shapeType;
    private double radius;
    private double length;
    private double width;

    public Shape(String shapeType, double radius, double length, double width) {
        this.shapeType = shapeType;
        this.radius = radius;
        this.length = length;
        this.width = width;
    }

    public double area() {
        if (shapeType.equals("circle")) {
            return Math.PI * (radius * radius);
        } else if (shapeType.equals("rectangle")) {
            return length * width;
        } else {
            throw new IllegalArgumentException("Unknown shape type");
        }
    }
}

// Usage
public class Main {
    public static void main(String[] args) {
        Shape circle = new Shape("circle", 5, 0, 0);
        Shape rectangle = new Shape("rectangle", 0, 4, 6);

        System.out.println(circle.area());
        System.out.println(rectangle.area());
    }
}

如本例所示,遵循里氏替換原則意味著我們應該能夠無縫地用子類別實例取代超類別實例。

遵循 LSP 的好處

  • 改進的程式碼可重複使用性:透過確保子類型可以取代其基本類型,使用基本類型的程式碼也可以與其任何子類型一起使用,從而促進程式碼重用。
  • 增強的可維護性:遵循LSP的程式碼更容易維護,因為它降低了修改或擴展程式碼庫時引入錯誤的風險。
  • 更好的可測試性:LSP 使為類別及其子類型編寫單元測試變得更加容易,因為測試可以針對基本類型編寫,並且應該適用於所有子類型。

介面隔離原則(ISP)

介面隔離原則是 Robert C. Martin 提出的五個 SOLID 原則之一。它指出:「不應強迫客戶端依賴他們不使用的介面」。

換句話說,使用多個特定於任務的介面比使用一個通用介面更好。

下面的範例展示了通用介面的用法。

public class Invoice {
  private Long InvoiceNo;

  public void generateInvoice() {
    // code to generate Invoice.
  }

  public void saveToFiles() {
    // code to save invoice as a file.
  }
}

使用像 MultifunctionPrinter 這樣的通用介面迫使我們實作不必要的方法,這被認為是不好的做法。讓我們探討一下如何將介面隔離原則套用到此場景。

介面

public class Invoice {
  private Long InvoiceNo;

  public void generateInvoice() {
    // code to generate Invoice.
  }
}

public class FileManager {
  public void saveToFiles(Invoice invoice) {
    // code to save invoice as a file.
  }
}

實施

public class Shape {
    private String shapeType;
    private double radius;
    private double length;
    private double width;

    public Shape(String shapeType, double radius, double length, double width) {
        this.shapeType = shapeType;
        this.radius = radius;
        this.length = length;
        this.width = width;
    }

    public double area() {
        if (shapeType.equals("circle")) {
            return Math.PI * (radius * radius);
        } else if (shapeType.equals("rectangle")) {
            return length * width;
        } else {
            throw new IllegalArgumentException("Unknown shape type");
        }
    }
}

// Usage
public class Main {
    public static void main(String[] args) {
        Shape circle = new Shape("circle", 5, 0, 0);
        Shape rectangle = new Shape("rectangle", 0, 4, 6);

        System.out.println(circle.area());
        System.out.println(rectangle.area());
    }
}

透過應用ISP,我們將其分成更小的、特定於角色的介面 ——例如印表機、掃描器和傳真。這允許每個類別(例如 BasicPrinter、AdvancedPrinter 或 FaxMachine)僅實現相關功能,從而促進模組化並減少不必要的依賴關係。

跟隨 ISP 的好處

  • 模組化和可重複使用程式碼:透過將大型介面分解為更小、更具體的接口,程式碼變得更加模組化和可重用。類別或模組可以僅實現它們需要的接口,從而減少不必要的依賴關係,並使在系統的不同部分之間重複使用程式碼變得更容易。
  • 降低程式碼複雜度:當類別或模組僅依賴它們所需的介面時,程式碼變得不那麼複雜且更容易理解。這是因為開發人員不必處理不必要的方法或依賴項。這些與其特定用例無關。
  • 提高可維護性:透過更小、更集中的介面,可以更輕鬆地維護程式碼。對一個介面的變更不太可能影響系統的其他部分,從而降低了引入錯誤或破壞現有功能的風險。
  • 更好的可測試性:更小、更集中的介面使得為各個組件編寫單元測試變得更容易。這是因為測試可以專注於特定的行為,而不會受到不相關的方法或依賴項的影響。
  • 增加靈活性:透過遵守ISP,系統變得更加靈活並且更容易擴展或修改。可以透過建立新介面或修改現有介面來新增功能或要求,而不會影響整個系統。

依賴倒置原則(DIP)

依賴倒置原則是SOLID的最終原則。這也是由 Robert C. Martin 介紹的。這促進了鬆散耦合的程式碼。

DIP說明了幾點:

  • 高層模組不應該依賴低層模組。
  • 兩者都應該依賴抽象。
  • 抽像不應該依賴細節。
  • 細節應該取決於抽象。

簡單來說,一個類別不應該直接依賴其他特定類別(具體實作),而應該依賴介面或抽象類別。這使得程式碼更加靈活且更易於維護,因為您可以在不更改依賴類別的情況下更換實作。

緊耦合代碼(無 DIP)

public class Invoice {
  private Long InvoiceNo;

  public void generateInvoice() {
    // code to generate Invoice.
  }

  public void saveToFiles() {
    // code to save invoice as a file.
  }
}

如上例所示,Computer 類別直接依賴 Keyboard 類別。

松耦合代碼(帶 DIP)

public class Invoice {
  private Long InvoiceNo;

  public void generateInvoice() {
    // code to generate Invoice.
  }
}

public class FileManager {
  public void saveToFiles(Invoice invoice) {
    // code to save invoice as a file.
  }
}

現在,Computer 依賴 InputDevice 接口,而不是特定的 Keyboard。這樣可以輕鬆切換到另一個輸入設備,例如 WirelessKeyboard,而無需修改 Computer 類別。

遵循 DIP 的好處

  • 鬆散耦合:透過依賴抽象而不是具體實現,程式碼的耦合變得不那麼緊密,使得更容易更改系統的一個部分而不影響其他部分。
  • 提高可維護性:低層模組的變化不會影響高層模組,使系統更容易維護和擴展。
  • 增強的可測試性:可以使用低階模組的模擬實作來測試高階模組,使測試更快、更可靠。
  • 提高可重複使用性:高層模組可以在不同的上下文中重複使用,而不需要更改它們所依賴的低層模組。

結論

總而言之,SOLID 原則:單一職責、開閉、里氏替換、介面隔離和依賴倒置為在物件導向程式設計中編寫乾淨、可維護和可擴展的程式碼提供了基本準則。

透過遵守這些原則,開發人員可以創建更易於理解、修改和擴展的系統,最終帶來更高品質的軟體和更有效率的開發流程。

概括

感謝您閱讀這篇文章!我希望您現在對 SOLID 原則以及如何應用它們來增強您的專案有了深入的了解。

追蹤我:
  • LinkedIn — @nsadisha
  • GitHub — @nsadisha
  • 中 — @nsadisha
  • Dev.to — @nsadisha

—薩迪莎·尼薩拉

以上是堅實的原則的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
上一篇:一點點Java17下一篇:一點點Java17