IOC控制反轉實例詳解
控制反轉(Inversion of Control,英文縮寫為IoC)是架構的重要特徵,並非物件導向程式設計的專用術語。它與依賴注入(Dependency Injection,簡稱DI)和依賴查找(Dependency Lookup)並沒有關係。
使用過Spring的開發者應該都對IOC控制反轉功能有所了解,最開始學習時應該都知道使用依賴注入來實現IOC的功能,本文來介紹使用IOC控制反轉思想的幾種設計模式。
依賴注入來實作IOC
注入依賴是IOC最基本的實作方式,也是最常用的一種物件導向設計方式之一。注入依賴如何達到控制反轉效果,先以一個例子開始:
public interface UserQueue {void add(User user);void remove(User user); User get(); }public abstract class AbstractUserQueue implements UserQueue {protected LinkedList<User> queue = new LinkedList<>(); @Overridepublic void add(User user) { queue.addFirst(user); } @Overridepublic void remove(User user) { queue.remove(user); } @Overridepublic abstract User get(); }public class UserFifoQueue extends AbstractUserQueue {public User get() {return queue.getLast(); } }public class UserLifoQueue extends AbstractUserQueue {public User get() {return queue.getFirst(); } }
#UserQueue
介面定義了公共的方法,用於在一個佇列中去存放User物件。 AbstractUserQueue則是為後續的繼承類,提供了一些公用的方法實作。最後的UserFifoQueue
和 UserLifoQueue,則分別實作了FIFO 和 LIFO 佇列。
這是實作子類別多態性的一種有效方式。
透過建立一個依賴UserQueue抽象類型(也稱為DI術語中的服務)的客戶端類,可以在執行時間注入不同的實現,而無需重構使用客戶端類別的程式碼:
public class UserProcessor {private UserQueue userQueue;public UserProcessor(UserQueue userQueue) {this.userQueue = userQueue; }public void process() {// process queued users here } }
UserProcessor展示了依賴注入確實是IOC的一種方式。
我們可以透過一些硬編碼方式 如 new 操作,直接在建構函數中實例化在UserProcessor中取得對佇列的依賴關係。但這是典型的程式碼硬編程,它引入了客戶端類別與其依賴關係之間的強耦合,並大大降低了可測性。
該類別在建構函式中宣告對抽象類別 UserQueue
的相依性。也就是說,依賴關係不再透過在建構函式中使用 new 操作, 相反,透過外部注入的方式,要麼使用依賴注入框架,要麼使用factory或builders模式。
使用依賴注入,客戶端類別的依賴關係的控制,不再位於這些類別中;而是在註入器中進行,看如下程式碼:
public static void main(String[] args) { UserFifoQueue fifoQueue = new UserFifoQueue(); fifoQueue.add(new User("user1")); fifoQueue.add(new User("user2")); fifoQueue.add(new User("user3")); UserProcessor userProcessor = new UserProcessor(fifoQueue); userProcessor.process(); }
#上述方式達到了預期效果,而且對UserLifoQueue的注入也簡單明了。
觀察者模式實現IOC
直接透過觀察者模式實現IOC,也是一種常見的直覺方式。廣義上講,透過觀察者實現IOC,觀察者模式通常用於在模型視圖的上下文中,追蹤模型物件的狀態的變化。
在一個典型的實作中,一到多個觀察者綁定到可觀察對象(也稱為模式術語中的主題),例如透過呼叫addObserver方法進行綁定。一旦定義了被觀察者和觀察者之間的綁定,則被觀察者狀態的變化都會觸發呼叫觀察者的操作。看下面範例:
public interface SubjectObserver {void update(); }
值改變時,會觸發呼叫上述這個很簡單的觀察者。在真實情況下,通常會提供功能更豐富的API,如需要保存變化的實例,或者新舊值,但是這些都不需要觀察action(行為)模式,所以這裡舉例盡量簡單。
下面,給一個被觀察者類別:
public class User {private String name;private List<SubjectObserver> observers = new ArrayList<>();public User(String name) {this.name = name; }public void setName(String name) {this.name = name; notifyObservers(); }public String getName() {return name; }public void addObserver(SubjectObserver observer) { observers.add(observer); }public void deleteObserver(SubjectObserver observer) { observers.remove(observer); }private void notifyObservers(){ observers.stream().forEach(observer -> observer.update()); } }
User類別中,當透過setter方法變更其狀態事,都會觸發呼叫綁定到它的觀察者。
使用主題觀察者和主題,以下是實例給出了觀察方式:
public static void main(String[] args) { User user = new User("John"); user.addObserver(() -> System.out.println("Observable subject " + user + " has changed its state.")); user.setName("Jack"); }
每當User物件的狀態透過setter方法進行修改時,觀察者將被通知並向控制台列印出一條訊息。到目前為止,給出了觀察者模式的一個簡單用例。不過,透過這個看似簡單的用例,我們了解到在這種情況下控制是如何實現反轉的。
觀察者模式下,主題就是起到」框架層「的作用,它完全主導何時何地去觸發誰的調用。觀察者的主動權被外放,因為觀察者無法主導自己何時被調用(只要它們已經被註冊到某個主題中的話)。這意味著,實際上我們可以發現控制被反轉的」事發地「— 當觀察者綁定到主題時:
user.addObserver(() -> System.out.println("Observable subject " + user + " has changed its state."));
上述用例,简要说明了为什么观察者模式是实现IoC的一种非常简单的方式。正是以这种分散式设计软件组件的形式,使得控制得以发生反转。
模板方法模式实现IOC
模板方法模式实现的思想是在一个基类中通过几个抽象方法来定义一个通用的算法,然后让子类提供具体的实现,这样保证算法结构不变。
我们可以应用这个思想,定义一个通用的算法来处理领域实体,看例子:
public abstract class EntityProcessor {public final void processEntity() { getEntityData(); createEntity(); validateEntity(); persistEntity(); }protected abstract void getEntityData();protected abstract void createEntity();protected abstract void validateEntity();protected abstract void persistEntity(); }
processEntity()
方法是个模板方法,它定义了处理实体的算法,而抽象方法代表了算法的步骤,它们必须在子类中实现。通过多次继承 EntityProcessor 并实现不同的抽象方法,可以实现若干算法版本。
虽然这说清楚了模板方法模式背后的动机,但人们可能想知道为什么这是 IOC 的模式。
典型的继承中,子类调用基类中定义的方法。而这种模式下,相对真实的情况是:子类实现的方法(算法步骤)被基类的模板方法调用。因此,控制实际是在基类中进行的,而不是在子类中。
总结:
依赖注入:从客户端获得依赖关系的控制不再存在于这些类中。它存由底层的注入器 / DI 框架来处理。
观察者模式:当主体发生变化时,控制从观察者传递到主体。
模板方法模式:控制发生在定义模板方法的基类中,而不是实现算法步骤的子类中。
以上是IOC控制反轉實例詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

在Java框架中,設計模式和架構模式的區別在於:設計模式定義了在軟體設計中解決常見問題的抽象解決方案,專注於類別和物件之間的交互,例如工廠模式。架構模式定義了系統結構和模組之間的關係,關注系統元件的組織和交互,如分層架構。

裝飾器模式是一種結構型設計模式,允許動態添加物件功能,無需修改原始類別。它透過抽象組件、具體組件、抽象裝飾器和具體裝飾器的協作實現,可以靈活擴展類別功能,滿足變化的需求。範例中,將牛奶和摩卡裝飾器添加到Espresso,總價為2.29美元,展示了裝飾器模式在動態修改物件行為方面的強大功能。

1.工廠模式:分離物件創建和業務邏輯,透過工廠類別建立指定類型的物件。 2.觀察者模式:允許主題物件通知觀察者物件其狀態更改,實現鬆散耦合和觀察者模式。

設計模式透過提供可重複使用和可擴展的解決方案來解決程式碼維護難題:觀察者模式:允許物件訂閱事件,並在事件發生時收到通知。工廠模式:提供了一種創建物件的集中式方式,而無需依賴特定類別。單例模式:確保一個類別只有一個實例,用於建立全域可存取的物件。

TDD用於編寫高品質PHP程式碼,步驟包括:編寫測試案例,描述預期功能並使其失敗。編寫程式碼,僅使測試案例通過,無需過度優化或詳細設計。測試案例通過後,優化和重構程式碼以提高可讀性、可維護性和可擴展性。

Guice框架應用了多項設計模式,包括:單例模式:透過@Singleton註解確保類別只有一個實例。工廠方法模式:透過@Provides註解建立工廠方法,在依賴注入時取得物件實例。策略模式:將演算法封裝成不同策略類,透過@Named註解指定具體策略。

適配器模式是一種結構型設計模式,允許不相容物件協同工作,它將一個介面轉換為另一個,使物件能夠順利互動。物件適配器透過建立包含被適配器對象的適配器對象,並實現目標接口,實現適配器模式。在一個實戰案例中,透過適配器模式,客戶端(如MediaPlayer)可以播放高級格式的媒體(如VLC),儘管本身僅支援普通媒體格式(如MP3)。

SpringMVC框架使用以下設計模式:1.單例模式:管理Spring容器;2.門面模式:協調控制器、視圖和模型互動;3.策略模式:根據請求選擇請求處理程序;4.觀察者模式:發布和監聽應用程式事件。這些設計模式增強了SpringMVC的功能和靈活性,使開發者可以創建高效、可維護的應用程式。
