核心要點
許多程序員(包括我自己,所以這是我公開的 mea culpa)認為控制反轉 (IoC) 不過是依賴注入 (DI) 的同義詞。這種想法有一個相當直觀的原因:如果DI 的目的是促進類的設計,使其外部協作者由周圍環境提供,而不是反過來查找它們,那麼這個過程可以有效地被視為一種IoC 的形式。但是,雖然 DI = IoC 這個等式通常有效,但控制反轉的概念本身實際上要廣泛得多。事實上,可以說 DI 是一個利用 IoC 優勢的特定用例,但它遠非唯一的一個。這讓我們回到起點;如果 DI 只是一種依賴 IoC 優勢的模式,那麼 IoC 究竟是什麼呢?傳統上,應用程序組件被設計為操作和控制執行環境,這種方法在某種程度上運行良好。例如,可以實現一個日誌記錄模塊來將數據記錄到文件中,以及如何以及何時記錄數據完全由模塊控制。日誌文件(在這種情況下是環境的一部分)只是一個外部的、被動的元素,不會影響模塊的工作方式。但是,假設我們需要擴展模塊的功能,並使其能夠額外地將數據記錄到數據庫,或者最終甚至通過電子郵件。升級模塊以公開額外功能將使其複雜性增加,隨著處理這些額外任務所需的邏輯打包在相同的 API 後面,它會變得越來越臃腫。這種方法有效,但根本無法擴展。這種情況可以通過一種相當簡單的方式解決。與其讓模塊完全負責將數據記錄到多個端點,我們可以將責任直接轉移到外部環境。模塊的實現將保持非常簡單,僅限於充當簡單的事件調度器。另一方面,環境將負責實現將數據記錄到與所討論的模塊完全獨立的端點所需的所有邏輯。毫不奇怪,在組件和環境之間反轉這些責任的過程正式被稱為控制反轉(或者在更輕鬆的術語中,好萊塢原則),並且在開發可擴展的、高度解耦的程序模塊時,它的實現可以是一個真正的提升。當然,IoC 是一種與語言無關的範例,因此可以在 PHP 世界中輕鬆使用它。
實現控制反轉——觀察領域對象
IoC 的確無處不在,因此很容易找到它的生產實現。首先想到的用例是依賴注入,但還有許多其他同樣具有代表性的用例,尤其是在事件驅動設計的領域。如果您想知道 IoC 在何種平行宇宙中與事件處理機制協同工作,請考慮 GoF 庫中的一個經典案例:觀察者模式。觀察者幾乎在任何地方都被使用,甚至通過JavaScript 在客戶端使用,它們是IoC 概念的突出示例;有一個高度解耦的主體專注於執行少數狹窄的任務,而不會污染周圍環境,而一個或多個外部觀察者負責實現處理主體觸發的事件所需的邏輯。如何處理事件,甚至處理新事件,完全是觀察者的責任,而不是主體的責任。一個例子可能是一種讓我的先前冗長說法更清晰的好方法。因此,假設我們已經實現了一個原始的領域模型,它定義了博客文章和評論之間的一對多關係。在這種情況下,我們將故意雄心勃勃,並使模型能夠發送電子郵件以在將新評論添加到帖子時通知系統管理員。老實說,在不訴諸 IoC 的情況下實現這樣的功能實際上將是一團糟,因為我們將要求領域對像做一些超出其範圍的事情。相反,我們可以採用基於 IoC 的方法並定義如下領域類:
(此處省略了代碼示例,因為這部分內容與問題要求的偽原創和保持圖片格式無關,且篇幅過長。)
將控制委託給外部環境——實現評論通知服務
構建一個能夠在向博客文章添加新評論時觸發電子郵件通知的觀察者服務是一個簡單的過程,它簡化為定義一個實現相關 update()
方法的類。 (此處同樣省略了代碼示例,原因同上。)
總結
控制反轉通常被認為是一個晦澀難懂的概念,尤其是在PHP 中,許多開發人員傾向於將其與普通的依賴注入聯繫起來,但它是一種簡單而強大的編程方法,如果正確實現,它是一種創建解耦、正交系統的絕佳方法,其組件可以輕鬆地隔離測試。如果您在應用程序中使用依賴注入(您確實在使用,對吧?),那麼您應該會感到您的程序員本能得到了很好的滿足,因為您已經在利用控制反轉提供的優勢。但是,正如我之前試圖演示的那樣,除了以正確的方式管理類依賴關係之外,還有很多情況適合這種方法。事件驅動設計當然就是一個很好的例子。
(此處省略了FAQ部分,原因同上。)
以上是PHP主|控制倒置 - 好萊塢原則的詳細內容。更多資訊請關注PHP中文網其他相關文章!