引言:設計模式是我們計畫中經常會涉及到的計畫進行重構、解構時的一種方法,像常見的單例模式、工廠模式、策略模式、裝飾器模式都是比較常用的,關於 23 種設計模式,大家可以找本書專門去翻看一下,在 Java 框架的源碼中也不例外,設計模式的使用實在是太多了,本文就來分析 Spring 中用到的設計模式。
題目
你了解的 Spring 都用到哪些設計模式?
推薦解析
工廠設計模式
優點
1) 封裝物件建立過程 :工廠模式將物件的建立過程封裝在工廠類中,客戶端程式碼無需關心具體的建立細節,只需透過工廠類獲取所需物件的例項,從而簡化了物件的例項化過程。
2) 解耦合 :客戶端程式碼與具體產品類解耦,減少了程式碼的依賴性,提高了程式碼的靈活性和可維護性。如果需要更換產品類,只需修改工廠類即可,而不必修改客戶端程式碼。
3) 復用性 :由於物件的建立邏輯集中在工廠類中,可以在多個地方重復使用,避免了重復的建立程式碼,提高了程式碼的復用性。
4) 單一職責原則 :工廠類專門負責物件的建立,遵循了單一職責原則,每個類都專註於自己的任務,程式碼結構清晰。
5) 更好的擴充套件性 :如果需要添加新的產品類,只需擴充套件工廠類即可,符合開閉原則,系統擴充套件性較好。
缺點
1) 類數量增加 :引入了工廠類之後,類的數量將會增加,增加了系統的抽象性和理解難度。
2) 增加了系統復雜度 :雖然工廠模式能夠將物件的建立過程封裝起來,但也引入了額外的復雜度和間接性,不適合建立簡單的物件。
3) 不易於理解 :對於初學者來說,理解工廠模式可能會增加一定的學習成本,需要理解工廠類、抽象產品類等概念。
使用場景
當一個類不知道它所需要的物件的類時(例如需要根據條件動態建立物件),可以使用工廠模式。
當一個類希望由它的子類別來指定所建立的物件時,可以使用工廠模式。
當類中的某些部份依賴於具體建立物件的時候,可以考慮使用工廠模式。
當系統需要動態地決定建立哪些類的物件時,可以使用工廠模式。
Spring 源碼
在 Spring 中,Bean 的建立通常透過工廠方法模式來實作。即透過一個工廠類(通常是實作了 FactoryBean 介面的類)來建立和管理 Bean 物件。
publicinterfaceFactoryBean<T> {
T getObject()throws Exception;
class<?> getObjectType();
booleanisSingleton();
}
在 Spring 中,Bean 的建立也可以透過抽象工廠模式來實作。Spring 提供了多種抽象工廠來管理不同型別的 Bean,例如 BeanFactory 和 ApplicationContext。
publicinterfaceBeanFactory{
Object getBean(String name)throws BeansException;
<T> T getBean(String name, class<T> requiredType)throws BeansException;
booleancontainsBean(String name);
...
}
單例設計模式
優點
1) 全域唯一例項 :確保一個類只有一個例項存在,可以節省系統資源,避免頻繁建立和銷毀物件。
2) 全域存取點 :提供一個全域的存取點來存取唯一例項,方便對例項進行統一的管理和操作。
3) 延遲例項化 :可以延遲物件的例項化,只有在第一次存取時才會建立例項,提高了系統的效能和資源利用率。
4) 避免多次例項化 :在多執行緒或分布式環境下,可以避免多次例項化相同的物件,確保物件的唯一性。
缺點
1) 可能引起資源浪費 :如果單例物件過早地建立並長時間占用記憶體,可能會引起資源浪費,特別是在物件占用大量資源時。
2) 不適合動態環境 :單例物件一旦建立之後,其狀態可能會一直保持,不適合需要頻繁改變狀態的場景。
3) 隱藏依賴關系 :單例模式會隱藏類之間的依賴關系,增加了類之間的耦合度,使得程式碼難以理解和維護。
使用場景
資源共享 :需要共享某個資源(如資料庫連線池、執行緒池等)的場景,可以使用單例模式確保全域唯一性,避免資源的多次建立和銷毀。
工具類 :某些工具類只需要一個例項來提供全域的功能,例如日誌工具類、配置管理類等。
控制例項數目 :某些類只需要一個例項來控制其例項數目,例如執行緒池、緩存管理器等。
全域狀態配置類 :某些類需要保存全域的配置資訊,例如系統設定類、全域狀態類等。
Spring 源碼
在 Spring 源碼中,最常見的使用單例設計模式的場景就是在建立 Bean 例項時使用單例模式。Spring 容器預設情況下會將所有的 Bean 物件作為單例物件進行管理,這樣可以節省資源,提高效能。
public classDefaultSingletonBeanRegistryimplementsSingletonBeanRegistry{
privatefinal Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
@Override
public Object getSingleton(String beanName){
returnthis.singletonObjects.get(beanName);
}
@Override
publicvoidregisterSingleton(String beanName, Object singletonObject){
synchronized (this.singletonObjects) {
Object oldObject = this.singletonObjects.get(beanName);
if (oldObject != null) {
thrownew IllegalStateException("Could not register object [" + singletonObject + "] under bean name '" + beanName +
"': there is already object [" + oldObject + "] bound");
}
this.singletonObjects.put(beanName, singletonObject);
}
}
// 其他方法...
}
下一期講解 Spring 的代理模式、樣版方法、觀察者模式,可以關註面試鴨公眾號後收到第一時間的推文。
其他補充
魚聰明 AI 的回答:
魚聰明 AI 地址:https://www.yucongming.com/
Spring 框架在設計和實作過程中廣泛運用了多種設計模式,以下是一些常用的設計模式在 Spring 中的套用:
單例模式(Singleton Pattern):在 Spring 中,預設情況下 Bean 是單例的,即容器中只會建立一個例項。透過單例模式,Spring 確保了 Bean 在整個應用程式中只會建立一次,節省資源,提高效能。
工廠模式(Factory Pattern):Spring 中的 BeanFactory 和 ApplicationContext 介面都是工廠模式的典型套用,用於建立和管理 Bean 例項。
代理模式(Proxy Pattern):Spring AOP(面向切面編程)功能中使用了代理模式,透過代理物件來實作橫切關註點的切面功能。
觀察者模式(Observer Pattern):Spring 事件機制基於觀察者模式,透過釋出-訂閱的方式實作事件的監聽和處理。
樣版模式(Template Pattern):Spring 中的 JdbcTemplate 和 RestTemplate 等樣版類都是基於樣版模式實作的,提供了統一的樣版方法供開發者使用。
策略模式(Strategy Pattern):Spring AOP 中的 Advice 和 Pointcut 就是策略模式的套用,透過不同的策略實作不同的橫切邏輯。
裝飾者模式(Decorator Pattern):Spring 中的裝飾者模式用於在 Bean 的初始化過程中添加額外的功能,如事務管理、日誌記錄等。
介面卡模式(Adapter Pattern):Spring MVC 中的 HandlerAdapter 就是介面卡模式的套用,用於適配不同型別的處理器。
除了上述列舉的設計模式外,Spring 框架還涵蓋了更多設計模式的套用,比如組合模式、樣版方法模式、享元模式等。透過合理運用設計模式,Spring 實作了松耦合、可延伸、易維護的特性,成為一個功能強大、靈活性高的框架。
歡迎交流
本文主要講解兩個設計模式,工廠模式和單例模式,可以詳細看下 Spring 的源碼進行分析,在面試時候提及設計模式,可以用源碼進行舉例,是一個不錯的選擇,在文末還有三個問題,歡迎在評論區留言!
1)Spring 框架中的依賴註入是如何實作的?它與傳統的依賴尋找有什麽區別和優勢?
2)單例設計模式可以套用在哪些場景?
3)工廠模式一般可以配合哪些設計模式?
點燃求職熱情!每周持續更新,海量面試題和大廠面經等你挑戰!趕緊關註面試鴨公眾號,輕松備戰春招和暑期實習!
往期推薦