设计模式之依赖倒转原则
一 ?原理?
依賴倒置原則又稱依賴倒置原則:
抽象不應該依賴細節,細節應該依賴于抽象。說白了,就是針對接口編程,不要針對實現編程。
依賴倒置原則包含三層含義:
1)高層模塊不應該依賴低層模塊,兩者都應該依賴其抽象;
2)抽象不應該依賴細節;
3)細節應該依賴抽象。
看了上面的解釋相信大家會和我一樣會有一些疑問在腦海里(你存在我深深的腦海里)下面來詳細說一說吧:
1)為什么要針對接口編程,而不是針對實現編程呢?
很簡單的一個例子,我們現在使用的電腦有各式的品牌,聯想、神舟、戴爾等等,
電腦需要用到鼠標,鍵盤;假設鼠標、鍵盤是針對某一個品牌的機器實現去做的話,那么我們將會遇到什么問題呢?
那么我們市面上的鍵盤和鼠標就都是各式各樣的,有一天鼠標,或鍵盤壞了,我們要怎么去買呢?難道記住這個電腦是什么品牌,什么型號,還有什么類型的去買么?這樣會瘋掉的。現在我們的電腦基本上都是使用USB接口的了,無論是鍵盤也好,鼠標也好,我們只要買USB接口的就可以使用了,同時,使用USB接口還可以有其他的擴展,只要實現了,這個接口,實現怎么樣都沒關系,例如,實現了USB接口的小臺燈,只要接上USB線就可以照明了;又如實現了USB
接口的充電器,接到我們的電腦上就可以充電了。?
2)高層模塊不應該依賴低層模塊,兩者都應該依賴其抽象又如何理解呢?這個問題也可以這么問:為什么要叫倒置(倒轉)呢?
在面向過程的開發中,為了使用常用的代碼可以復用,一般都會把這些常用的代碼寫成許許多多函數的程序庫,這樣我們做新項目的時候,就去調用這些函數就可以了。
例如:我們做的項目大多要訪問數據庫,所以我們就把數據庫的代碼寫成了函數,每次做新項目時就去調用這些函數,這也就是高層依賴于低層模塊了。
問題就出現在這里了,我們在做新項目的時候,會發現業務邏輯的高層模塊是一樣的,我們希望能重用這些高層模塊,但是這些高層模塊和低層模塊的數據庫綁定在一起了,這樣我們就沒辦法復用這些高層模塊了,這樣就。
如果我們的高層模塊和低層模塊都依賴于抽象,具體一點就是依賴于接口或抽象類,只要接口夠穩定,那么任何一個的更改都不用擔心其他受到影響了。
3)為什么依賴了抽象的接口或是抽象類,就不怕更改了呢?要解決這個問題,先看看里氏替換原則。
里氏替換原則:
一個軟件實體如果使用的是一個父類的話,那么一定適用于其子類,而且它察覺不出父類對象和子類對象的區別。也就是說,在軟件里面,把父類都替換成它的子類,程序的行為沒有變化;
簡單的說:子類型必須能夠替換掉它們的父類型。例如:企鵝在生物學分類上是屬于鳥的,但是在編程中,企鵝就不能以父類的(鳥)的身份出現。
假設有一個鳥的父類,擁有一個會飛的方法fly(),我們是不能讓企鵝繼承于鳥的,這樣當子類可以替換掉父類,軟件單位的功能不受到影響時,父類才能真正的被復用,
而子類也能夠在父類的基礎上添加新的行為。例如:貓是繼承動物類的,以動物的身份擁有吃、喝、跑、叫等行為,
可當某一天,我們需要狗、牛、羊也擁有類似的行為,由于它們都是繼承于動物,所以除了更改實例化的地方,程序其他地方就需要改變了。
正是由于子類型的可替換性才使得使用父類類型在的模塊在無需修改的情況下就可以擴展。咱們來看看UML圖:
高層模塊依賴于接口或抽象類,低層模塊實現接口或抽象類。依賴倒置原則其實就是誰也不依靠誰,除了約定的接口,這樣大家都可以靈活自由了。
二 案例
背景1:公司是福特和本田公司的金牌合作伙伴,現要求開發一套自動駕駛系統,只要汽車上安裝該系統就可以實現無人駕駛,該系統可以在福特和本田車上使用,只要這兩個品牌的汽車使用該系統就能實現自動駕駛。于是有人做出了分析如圖一。
對于圖一分析:我們定義了一個AutoSystem類,一個FordCar類,一個HondaCar類。FordCar類和HondaCar類中各有三個方法:Run(啟動Car)、Turn(轉彎Car)、Stop(停止Car),當然了一個汽車肯定不止這些功能,這里只要能說明問題即可。AutoSystem類是一個自動駕駛系統,自動操縱這兩輛車。
代碼實現:
public class HondaCar {
Java代碼???
代碼分析:上面的程序確實能夠實現針對Ford和Honda車的無人駕駛,但是軟件是在不斷變化的,軟件的需求也在不斷的變化。
背景2:公司的業務做大了,同時成為了通用、三菱、大眾的金牌合作伙伴,于是公司要求該自動駕駛系統也能夠安裝在這3種公司生產的汽車上。于是我們不得不變動AutoSystem:
public class AutoSystem
Java代碼???
}分析:這會給系統增加新的相互依賴。隨著時間的推移,越來越多的車種必須加入到AutoSystem中,這個“AutoSystem”模塊將會被if/else語句弄得很亂,而且依賴于很多的低層模塊,只要低層模塊發生變動,AutoSystem就必須跟著變動,
它最終將變得僵化、脆弱。
導致上面所述問題的一個原因是,含有高層策略的模塊,如AutoSystem模塊,依賴于它所控制的低層的具體細節的模塊(如HondaCar()和FordCar())。如果我們能夠找到一種方法使AutoSystem模塊獨立于它所控制的具體細節,那么我們就可以自由地復用它了。我們就可以用這個模塊來生成其它的程序,使得系統能夠用在需要的汽車上。OOD給我們提供了一種機制來實現這種“依賴倒置”。
這兒有一個“AutoSystem”類,它包含一個“ICar”接口。這個“AutoSystem”類根本不依賴于“FordCar”和“HondaCar”。所以,依賴關系被“倒置”了:“AutoSystem”模塊依賴于抽象,那些具體的汽車操作也依賴于相同的抽象。
于是可以添加ICar
public interface ICar
Java代碼???
現在AutoSystem系統依賴于ICar 這個抽象,而與具體的實現細節HondaCar、FordCar、BmwCar無關,所以實現細節的變化不會影響AutoSystem。對于實現細節只要實現ICar 即可,即實現細節依賴于ICar 抽象。
?
綜上:
一個應用中的重要策略決定及業務模型正是在這些高層的模塊中。也正是這些模型包含著應用的特性。但是,當這些模塊依賴于低層模塊時,低層模塊的修改將會直接影響到它們,迫使它們也去改變。這種境況是荒謬的。應該是處于高
層的模塊去迫使那些低層的模塊發生改變。應該是處于高層的模塊優先于低層的模塊。無論如何高層的模塊也不應依賴于低層的模塊。而且,我們想能夠復用的是高層的模塊。通過子程序庫的形式,我們已經可以很好地復用低層的模塊了。當高層的模塊依賴于低層的模塊時,這些高層模塊就很難在不同的環境中復用。但是,當那些高層模塊獨立于低層模塊時,它們就能很簡單地被復用了。這正是位于框架設計的最核心之處的原則。
?
總結:依賴倒置原則
A.高層次的模塊不應該依賴于低層次的模塊,他們都應該依賴于抽象。
B.抽象不應該依賴于具體,具體應該依賴于抽象。
總結
以上是生活随笔為你收集整理的设计模式之依赖倒转原则的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一个sql题目, 统计每年每月的信息
- 下一篇: java 仅有类名 构造类_java –