暸解依賴反轉原則(Dependency inversion principle,DIP)並增加可測試性

今天不知道為什麼突然很順手的用 Mockery 的方式寫完了一個 Method 的測試,有感而發想用這篇文章把它記錄下來。

 

依賴注入是一個花俏的名詞,實際上我們利用了這個技巧來達成減少對物件的相依性及可測試性,假設我今天做了一個電影票價的爬蟲,那在我爬得這些資料之後,我需要利用各個影城所提供的不同優惠來算出相對應的票價,趕時間的寫法:

 

建立一個電影控制器,當我們想要取得票價時,傳入電影院的名稱建立一個相對應的電影院物件,並在其中包含一個 countPrice method 負責依照票價及折扣算出新價錢來。

然後分別依照影城名稱建立不同的類別

 

秀泰:

%e8%9e%a2%e5%b9%95%e5%bf%ab%e7%85%a7-2016-11-25-%e4%b8%8b%e5%8d%884-48-51

 

環球:

%e8%9e%a2%e5%b9%95%e5%bf%ab%e7%85%a7-2016-11-25-%e4%b8%8b%e5%8d%884-48-15

 

威秀:

%e8%9e%a2%e5%b9%95%e5%bf%ab%e7%85%a7-2016-11-25-%e4%b8%8b%e5%8d%884-48-34

目前的做法看起來沒有問題,但是如果我的電影院不會只有三家呢?每當我新增了一家新的電影院的時候我就必須得回到 switch 中新增一個 case,也許你說全台灣電影院也就那幾家啊!大不了我全部手動新增完,那如果我想要擴大爬蟲的範圍到全亞洲呢?那我的 case 可能就得無限的新增下去,不僅變得難以維護,當我需求有變動的時候也很難更改。

 

interface 這時候就派上用場了,首先我們建立一個 Movie Interface 來約束底下的 Class,強迫每一個 implement 的 Class 都必須擁有(實作)我在 interface 中要求的 methods

%e8%9e%a2%e5%b9%95%e5%bf%ab%e7%85%a7-2016-11-25-%e4%b8%8b%e5%8d%8811-33-40

建立 Interface 約束底下的類別

 

要求類別實現 interface 中的方法

要求類別實現 interface 中的方法

 

如此一來我們就可以強迫每一家電影院都要幫我算出折扣後的價錢是多少,再也不用陷入 if – else 或是 switch 中了,也從原本需要相依三個類別變成只需要依賴 MovieInterface。

%e8%9e%a2%e5%b9%95%e5%bf%ab%e7%85%a7-2016-11-25-%e4%b8%8b%e5%8d%8811-53-43

現在我們可以隨意在 createTheater 中建立任何一種的電影院,並注入到 getPrice method 中取得折扣票價。

如此一來我們就從依賴多個電影院類別變成只依賴於 Interface,大大的減少了我們注入類別的數量。

 

結尾順便推銷一下 Laravel ,Laravel 中大量使用了這個技巧來解耦合及可測試性,建議你也可以加入 Laravel 的行列來挖掘他的建構模式及思維,能夠有效幫助你了解依賴注入、依賴反轉、工廠模式等技巧。(github 連結

 

Panigale

喜歡 Modern Web的打造方式及簡潔優美的程式碼,也持續在學習有關於 PHP、Javascript的基本觀念及使用技術。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *