面向物件的五大設計原則之依賴倒置原則
依賴倒置原則(depend ence inversion principle,簡稱DIP),簡單來說就是將依賴關係倒置為依賴介面,具體就是,上層模組不應該依賴於下層模組,它們共同依賴於一個抽象(父類不能依賴子類,應該共同依賴於抽象類)。抽象不能依賴於具體,但是具體應該依賴於抽象,我們要注意下,咱們這裡的介面並不是指狹義上的介面。
因為介面體現了對問題的抽象,同時又因為抽象一般是相對穩定的,或者說相對變化不是太頻繁,而具體是很容易就會產生變化的,所以我們依賴抽象是實現程式碼擴充套件和執行期內繫結(多型)的基礎,只要實現了該抽象的子類,就都可以被類的使用者所使用。
咱們再來看下這個擴充套件性的概念啊,這個擴充套件性啊,通常是指對已知行為的擴充套件,並且咱們知道,介面是相對穩定的,所以,我們無論是用多麼先進的設計模式,也不可能做到不需要修改程式碼就達到以不變應萬變的地步,所以嘞,這個依賴倒置原則,我認為是最難理解和實現的。
先來看一個程式碼段:
interface employee { public function working(); } class teacher implements employee { public function working() { // TODO: Implement working() method. echo "teacher"; } } class coder implements employee { public function working() { // TODO: Implement working() method. echo "coder"; } } class w_1 { public function work() { $teacher = new teacher(); $teacher->working(); } } class w_2 { private $a; public function set(employee $a) { $this->a = $a; } public function work() { $this->a->working(); } } $w_1 = new w_1(); $w_1->work(); $w_2 = new w_2(); $w_2->set(new teacher()); $w_2->work();
咱們來梳理下上述程式碼,首先上述程式碼的w_1類的work方法,它的實現是依賴於teacher,但是w_2呢,是依賴於抽象來實現的,這樣一來,我們就可以把需要的物件通過引數傳入,就可以獲取了,上述程式碼呢,通過介面,實現了一定程度上的解耦,但仍然是有限的,我們不僅僅是使用介面,使用工廠模式也是可以簡單來實現一定程度的解耦和依賴倒置的。
在w_2類中,teacher例項通過set方法傳入,實現了工廠模式,這樣的方式是屬於硬編碼的,為了實現程式碼的進一步擴充套件,我們會把這個依賴關係寫在配置檔案裡,指明瞭w_2類需要一個teacher例項物件,並且專門有一個程式來檢測配置是否正確(如所以來的類檔案是否存在等)以及載入配置中所依賴的實現,這個檢測程式,我們可以稱為IOC容器(inversion of control)。
IOC是依賴倒置原則的同義詞,偶爾還會關聯到DI、DS等概念,DI就是指依賴注入,DS就是指依賴查詢,一般認為這兩個東西是IOC的兩種實現,不過,隨著某些概念的演化,這幾個概念之間的關係也變得很模糊,也有人認為IOC就是依賴注入,因為他們認為依賴注入的描述比IOC更加的貼切,咱們在這裡就不討論這個了啊。
事實上,很多設計模式裡已經隱含了依賴倒置原則,我們也在有意無意的進行著一些依賴倒置的工作,這個依賴倒置它的核心是解耦,脫離了這個,一切都是本末倒置,並且在PHP裡,目前來說還沒有一個較為完善的IOC容器,並且如果是通過PHP來實現IOC容器等功能的話,倒不是不可以,只是從技術實現和執行效率方面來看的話,都是不符合我們使用PHP來進行開發的初衷的,咱們在這裡呢,不對這個原則的好壞進行判斷,只是簡單介紹下這個原則。
滿足依賴倒置原則有兩個方面:
- 每個較高層次的類都為它所需要的服務提出一個介面宣告,較低層次的類實現這個介面
- 每個高層類都通過該抽象介面使用服務
好啦,本次記錄就到這裡了。
如果感覺不錯的話,請多多點贊支援哦。。。