Skip to main content

SOLID 原則

SOLID 原則是物件導向程式(OOP)的 5 個基本原則,遵守這些原則的程式碼會更容易維護、擴充與修改。

字母代表基本概念
S單一職責 SRP物件、函式和方法應該僅具有一種單一功能。
O開放封閉 OCP模組、方法和類別應對於擴充是開放的,對於修改是封閉的。
L里氏替換 LSP程式中的物件應該可以在不改變程式正確性的前提下,被它的子類所替換。
I介面隔離 ISP多個特定客戶端介面要好過於一個廣泛用途的介面。
D依賴反轉 DIP高層模組不應該依賴於低層模組,兩者皆應該依賴於抽象介面。

筆者個人認爲這 5 項原則的重要程度爲:

  • 非常重要
    • S-單一職責
    • D-依賴反轉
  • 重要
    • O-開放封閉
    • I-介面隔離
  • 一般
    • L-里氏替換

單一職責

Single responsibility principle (SRP)

  • 物件、函式和方法應該僅具有一種單一功能。

開放封閉

Open–closed principle (OCP)

  • 模組、方法和類別應對於擴充是開放的,對於修改是封閉的。
    • 意指:應該將軟體設計成不對其修改就能擴展功能。

里氏替換

Liskov substitution principle (LSP)

  • 程式中的物件應該可以在不改變程式正確性的前提下,被它的子類所替換。

介面隔離

Interface segregation principle (ISP)

  • 多個特定客戶端介面要好過於一個廣泛用途的介面。

依賴反轉

Dependency inversion principle (DIP)

  • 高層模組不應該依賴於低層模組,兩者皆應該依賴於抽象介面。
  • 抽象介面不應該依賴於具體實作,具體實作應該依賴於抽象介面。

範例

沒有依賴反轉的一般寫法:

// 沒有依賴反轉的一般寫法。
class Engine
{
void Start() { /* Some code here. */ }
}

class Car
{
// 高層模組「Car」直接依賴於低層模組「Engine」。
Engine MyEngine = new Engine();

// Some code here.
}

依賴反轉的基本寫法:

// 依賴反轉的基本寫法。
interface EngineInterface
{
void Start();
}

// 低層模組「Engine」實作(Implement)了介面「EngineInterface」。
class Engine : EngineInterface
{
void Start() { /* Some code here. */ }
}

class Car
{
// 高層模組「Car」不直接依賴於低層模組「Engine」,而是依賴於介面「EngineInterface」。
EngineInterface MyEngine = new Engine();

// Some code here.
}

依賴反轉的進階寫法:

// 依賴反轉的進階寫法。
interface EngineInterface
{
void Start();
}

class Engine : EngineInterface
{
void Start() { /* Some code here. */ }
}

class Car
{
EngineInterface MyEngine = null;

// 使用依賴注入(Dependency Injection,DI)的方式實現控制反轉(Inversion of Control,IoC)。
// 將低層模組「Engine」在高層模組「Car」之外實體化後,才透過建構子的參數傳入「Car」。
Car(EngineInterface engine)
{
MyEngine = engine;
}

// Some code here.
}
// 實際呼叫「Car」時。
Engine V8Engine = new Engine();
Car MySuperCar = new Car(V8Engine);

參考資料