跳到主要內容

DIP: Dependency Inversion Principle

DIP (Dependency Inversion Principle)相依性反向原則:要依賴於抽象,而不要依賴於具體類別。
這個經驗法則建議程式中所有的關係都應終止於介面或抽象類別。以下幾種情形況都應該遵循DIP
  • 變數的類別宣告
  • 參數的類別宣告
  • 方法的傳回型態宣告
  • 型態的轉換
所以這個原則很難遵守,幾乎每個程式都會多少違反DIP。

若一個物件存在其抽象類別,就應當在任何參照此物件的地方使用抽象類別,例如在Java中應該使用介面List而不要直接使用ArrayList
List books = new ArrayList();

DIP假定所有的具體類別都是會變化的並不完全正確,因為某些具體類別是相當的穩定因此並不需要為此發明一個抽象型態。

我自己的經驗是:就先照想法做,不行時再refactor吧!物件生成是以效能為代價,若所有物件都是指向抽象類別,會和SmallTalk一樣慢到不行。

Update:感謝qing的指正,使用抽象類別宣告的影響幾乎感受不到,為了彈性應該盡可能使用抽象類別設計。


參考資料:
軟體工程(Software Engineering;SE)

留言

匿名表示…
我是覺得啦
hardcode 任何一個名稱就會相依於這個名稱
當這個名稱代表的意義愈一般(也就是愈抽象
時)受到變動而影響的機會就會愈小, 因為這
個名稱所代表的概念是比較一般的, 範圍比
較廣的, 比較有機會繼續容納變動後的概念
這是為什麼希望使用的名稱(也就意謂了概念
) 是愈抽象的愈好

不過文中提到如果都做 upcasting 速度會
變慢可能就不見得. 對採用dynamic
binding的程式語言來說, 就算沒有做
upcasting, 應該也是花一樣的時間來找出
要invoke的method究竟是那一個
鳥毅寫道…
我覺得還是有差,所以做了個小實驗。
時間差一點點啦,幾乎感覺不出來。
我常用子類別另一個原因是子類別的功能比較多,偶爾會直接用子類別的方法。
未cast花3084毫秒,有cast花3153毫秒
測試程式如下:

mport java.util.*;
public class TestSpeed {
public static void main(String[] args) {
//較前的會慢一點 可能是HotSpot 的JIT影響,有興趣的人可以分開測
noCast();
cast();
}

public static void noCast() {
java.util.Calendar start = java.util.Calendar.getInstance();
long lstart = start.getTimeInMillis();

for (int j = 0; j < 100; j++) {
for (int i = 0; i < 65530; i++) {
ArrayList l = new ArrayList();
l.add(i);
l.clear();
}
}
java.util.Calendar end = java.util.Calendar.getInstance();
long lend = end.getTimeInMillis();

System.out.println("未Cast經過:" + (lend - lstart));
}

public static void cast() {
java.util.Calendar start = java.util.Calendar.getInstance();
long lstart = start.getTimeInMillis();

for (int j = 0; j < 100; j++) {
for (int i = 0; i < 65530; i++) {
List l = new ArrayList();
l.add(i);
l.clear();
}
}
java.util.Calendar end = java.util.Calendar.getInstance();
long lend = end.getTimeInMillis();
System.out.println("有Cast經過:" + (lend - lstart));
}
}
匿名表示…
經由 interface 呼叫 method (使用 invokeinterface) 通常會比直接呼叫 (使用 invokevirtual) 慢。

不過以上面需要 cast 的這個例子,假如 Java compiler 夠聰明的話,應該要能夠用 invokevirtual 來呼叫 add() 及 clear(),這樣兩者的 performance 就沒有差別了。

這個網誌中的熱門文章

自然人憑證讀卡機驅動程式

鳥毅用的是第一代的自然人憑證讀卡機,EZ100PU(後來有同事買EZmini可以讀SIM卡似乎更好),每年報稅時用一次。 本來只是要申請些政府業務,一時之間找不到光碟,沒想到在 驅動程式下載 居然看到Linux和Mac的驅動程式,剩下的就是政府單位的網頁和程式應該改版了吧!!!

DBeaver 介面語言

DBeaver是我個人頗常用的一套跨平台Database管理工具,最近升級後發現Windows版本居然變成簡體中文,而且無法切換為英文。

如何將較高版本SQL Server複製到低版本SQL Server (降級為舊版)並保留權限及資料庫圖表

一般若是要將SQL Server裡的Database轉往其他Server時,最簡單的方式就是備份(Backup)後再還原(Restore),或者是䣃離(detach)後附加(attach)。 但是很不幸地,若是由較低版本(e.g. 2008)到較高版本(e.g. 2012)要怎麼辦呢?