Ch11: DIP - 依賴反轉原則
Dependency inversion principle
DIS 最主要的目的在於解耦 (Decoupling),其概念如下。
高層次的類別不應該依賴於低層次的類別,兩者都應該依賴於抽象的介面。
抽象介面不應該依賴於具體的實作,具體的實作應該依賴於抽象介面。
什麼是高層次與低層次的類別呢?
- 低層次的類別,用來實作基礎操作,例如磁碟操作,網路數據傳輸和資料庫連線。
- 高層次的類別,包含複雜的業務邏輯,操作低層次的類別來執行特定操作。
常見開發流程:低層次做完能動,再拉出高層次,這樣容易讓用來實現業務邏輯的高層次類別依賴於低層次的類別。
依賴倒轉原則建議改變這種依賴方式。
- 最好使用業務術語來命名高層次類別的方法,如 BudgetReport。
- 基於抽象介面建立高層次類別,而不是基於低層次的具體類別,這會比原始的依賴關係靈活很多。
- 一旦低層次的類別實現這些介面,他們將依賴於業務邏輯層,從而倒轉了原始的依賴關係。
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. 依賴於抽象,而非具體。