PHP程式設計師如何理解IoC/DI
思想
思想是解決問題的根本
思想必須轉換成習慣
構建一套完整的思想體系是開發能力成熟的標誌
——《簡單之美》(前言)
.
“成功的軟體專案就是那些提交產物達到或超出客戶的預期的專案,而且開發過程符合時間和費用上的要求,結果在面對變化和調整時有彈性。”
——《面向物件分析與設計》(第3版)P.236
術語介紹
——引用《Spring 2.0 技術手冊》林信良
非侵入性 No intrusive
-
框架的目標之一是非侵入性(No intrusive)
-
元件可以直接拿到另一個應用或框架之中使用
-
增加元件的可重用性(Reusability)
容器(Container)
-
管理物件的生成、資源取得、銷燬等生命週期
-
建立物件與物件之間的依賴關係
-
啟動容器後,所有物件直接取用,不用編寫任何一行程式碼來產生物件,或是建立物件之間的依賴關係。
IoC
-
控制反轉 Inversion of Control
-
依賴關係的轉移
-
依賴抽象而非實踐
DI
-
依賴注入 Dependency Injection
-
不必自己在程式碼中維護物件的依賴
-
容器自動根據配置,將依賴注入指定物件
AOP
-
Aspect-oriented programming
-
面向方面程式設計
-
無需修改任何一行程式程式碼,將功能加入至原先的應用程式中,也可以在不修改任何程式的情況下移除。
分層
表現層:提供服務,顯示資訊。
領域層:邏輯,系統中真正的核心。
資料來源層:與資料庫、訊息系統、事務管理器及其它軟體包通訊。
——《企業應用架構模式》P.14
程式碼演示IoC
假設應用程式有儲存需求,若直接在高層的應用程式中呼叫低層模組API,導致應用程式對低層模組產生依賴。
/** * 高層 */ class Business { private $writer; public function __construct() { $this->writer = new FloppyWriter(); } public function save() { $this->writer->saveToFloppy(); } } /** * 低層,軟盤儲存 */ class FloppyWriter { public function saveToFloppy() { echo __METHOD__; } } $biz = new Business(); $biz->save(); // FloppyWriter::saveToFloppy
假設程式要移植到另一個平臺,而該平臺使用USB磁碟作為儲存介質,則這個程式無法直接重用,必須加以修改才行。本例由於低層變化導致高層也跟著變化,不好的設計。
正如前方提到的
控制反轉 Inversion of Control
依賴關係的轉移
依賴抽象而非實踐
程式不應該依賴於具體的實現,而是要依賴抽像的介面。請看程式碼演示
/** * 介面 */ interface IDeviceWriter { public function saveToDevice(); } /** * 高層 */ class Business { /** * @var IDeviceWriter */ private $writer; /** * @param IDeviceWriter $writer */ public function setWriter($writer) { $this->writer = $writer; } public function save() { $this->writer->saveToDevice(); } } /** * 低層,軟盤儲存 */