2015-04-21 55 views
1

我正在自學有關S.O.L.I.D的原則。面向對象編程時遇到麻煩了解所有的細節在信d依賴倒置原則(適用於Java)

我讀了維基百科(http://en.wikipedia.org/wiki/Dependency_inversion_principle)項,我不理解所有放在圖中(依賴反轉原則。):

http://en.wikipedia.org/wiki/Dependency_inversion_principle#/media/File:DIPLayersPattern_v2.png

我注意到有兩種不同類型的箭頭 - 一個是虛線和一個爲固體。

根據我目前的理解,虛線表示Java中的「implements」關鍵字的等價物,實線表示關鍵字「extends」。

這是正確的解釋嗎?

回答

3

這可能澄清一些事情:

Explanation of the UML arrows

注意圖像的Visual Studio,但我認爲最的信息就相當於與大多數UML文檔。

虛線表示「工具」

在UML中的實體的命名是扔我有點太相當於......看來Policy依賴描述在接口上到底層模塊的合同Mechanism

然而,第二條(實線)應該是繼承的代表(至少我相信)。當Policy引用具體的Mechanism時,Mechanism實現接口(抽象)Policy而不是在應用DIP之前。

它試圖傳達的主要是類不應該依賴於其他類,但它們可以依賴於抽象(接口)而不是混凝土。

這是最簡單的例子:具有依賴於較低級別模塊的原始Foo/Logger。

// "Low level Module" Mechanism equivilant 
public class Logger { 
    public void logInformation(String logInfo) { 
     System.out.println(logInfo); 
    } 
} 

// "High level module" Policy equivalent. 
public class Foo { 
    // direct dependency of a low level module. 
    private Logger logger = new Logger(); 

    public void doStuff() { 
     logger.logInformation("Something important."); 
    } 
} 

在上文中,Foo依賴於具體實現的Logger。這可重構本身(有幾種方法來做到這一點。注意,這只是一個)

public interface ILogger { 
    void logInformation(String logInfo); 
} 

public class Logger implements ILogger { 
    @Override 
    public void logInformation(string logInfo) { 
     System.out.println(logInfo); 
    } 
} 

public class Foo { 
    private ILogger logger; 
    public void setLoggerImpl(ILogger loggerImpl) { 
     this.logger = loggerImpl; 
    } 

    public void doStuff() { 
     logger.logInformation("Something important."); 
    } 
} 

在這個重構,Foo不再依賴於Logger,但現在使用的界面​​- 這意味着你可以切換和退出在運行時,實例化對象等ILogger的實現

你可以消耗Foo這樣:

Foo foo = new Foo(); 
ILogger logger = new Logger(); 
foo.setLoggerImpl(logger); 
foo.doStuff(); 

這當然會,打印控制「重要的東西」。現在如果您不想登錄到控制檯,而是登錄到數據庫,會發生什麼?

public class LoggerToDb implements ILogger { 
    @Override 
    public void logInformation(string logInfo) { 
     DbContext databaseContext = new DbContext(); 
     databaseContext.insertLog(logInfo); 
    } 
} 

,可能現在被消耗爲:

Foo foo = new Foo(); 
ILogger logger = new LoggerToDb(); 
foo.setLoggerImpl(logger); 
foo.doStuff(); 

注意什麼怎麼了你Foo實現改變,因爲Foo是不依賴於Logger,而是​​- 用這種方法,我們可以提供一個新的抽象的結晶,並將它換成Foo甚至沒有觸及Foo!漂亮的國際海事組織。在上面的例子中我建立的對象,並提供一個實現

注意,這也可以用類似Java的春天IoC框架來完成。

+0

@LuiggiMendoza感謝,根本不會拿到的是語法正確的:) – Kritner

+0

我認爲你是依賴注入和依賴倒置混合起來。 DIP適用於模塊間依賴關係,是對標準分層體系結構的改進。重點是模塊之間的關係。 [更多資訊](https://books.google.ca/books?id=X7DpD5g3VP8C&pg=PA123&lpg=PA123&dq=improved+layered+architecture+dependency+inversion+principle&source=bl&ots=tRBNLGD9YS&sig=8Zrz_2ANj29vXYNnEAHssA95dGI&hl=fr&sa=X&ei=dD44VdfdGozToAThh4HwAQ&ved= 0CCgQ6AEwAQ#v = onepage&q =改進%20layered%20architecture%20dependency%20inversion%20principle&F = FALSE) – plalx

+0

@plalx嗯...我的印象是,DI是實現DIP的一個方法 - 我沒有特別要求它在我例如(因爲它在維基文章OP中引用過),但是'ILogger'由'Foo'「擁有」,而不是'Logger'或任何其他'ILogger'實現。從我讀過的文章中所描述的DIP ...你能澄清一下錯過了什麼嗎? – Kritner

3

虛線表示源代碼依賴關係。帶有空白三角形的實線表示特殊類型的依賴關係:類繼承或接口實現。

在此圖中,策略服務和機制服務是抽象,策略服務是更高層次的抽象。機制和效用是細節。

政策對機制和實用程序(從政策開始將達到這些細節控制流程)一個明顯的運行依賴,並在一個較低的水平機制具有效用相似的運行依賴。但是,在源代碼級別策略僅取決於策略服務,而機制也取決於策略服務。這是依賴倒置。