Skip to main content

Ch11: DIP - 依賴反轉原則

Dependency inversion principle

DIS 最主要的目的在於解耦 (Decoupling),其概念如下。

高層次的類別不應該依賴於低層次的類別,兩者都應該依賴於抽象的介面。

抽象介面不應該依賴於具體的實作,具體的實作應該依賴於抽象介面。

什麼是高層次與低層次的類別呢?

  • 低層次的類別,用來實作基礎操作,例如磁碟操作,網路數據傳輸和資料庫連線。
  • 高層次的類別,包含複雜的業務邏輯,操作低層次的類別來執行特定操作。

常見開發流程:低層次做完能動,再拉出高層次,這樣容易讓用來實現業務邏輯的高層次類別依賴於低層次的類別。

依賴倒轉原則建議改變這種依賴方式。

  1. 最好使用業務術語來命名高層次類別的方法,如 BudgetReport。
  2. 基於抽象介面建立高層次類別,而不是基於低層次的具體類別,這會比原始的依賴關係靈活很多。
  3. 一旦低層次的類別實現這些介面,他們將依賴於業務邏輯層,從而倒轉了原始的依賴關係。

Example

  • Bad way:
class MySqlDatabase {
insert() {
// ...
}

update() {
// ...
}

delete() {
// ...
}
}

class BudgetReport {
private mySqlDatabase: MySqlDatabase;

constructor(mySqlDatabase: MySqlDatabase) {
this.mySqlDatabase = mySqlDatabase;
}

open(date: string) {
//...
}

save() {}
}
caution

高層次的類別不應該去關注資料存儲的細節。

  • Good way:
interface Database {
insert(): void;

update(): void;

delete(): void;
}

class MySql implements Database {
insert(): void {
// ...
}

update(): void {
// ...
}

delete(): void {
// ...
}
}

class MongoDB implements Database {
insert(): void {
// ...
}

update(): void {
// ...
}

delete(): void {
// ...
}
}

class BudgetReport {
private database: Database;

constructor(database: Database) {
this.database = database;
}

open(date: string) {
//...
}

save() {}
}
info

Depends on abstractions, not on concretions. 依賴於抽象,而非具體。