適配器模式介紹
適配器模式(Adapter Pattern)是作為兩個不兼容的接口之間的橋梁。這種類型的設計模式屬于結構型模式,它結合了兩個獨立接口的功能。
應用場景:
-
1、系統需要使用現有的類,而此類的接口不符合系統的需要。
-
2、想要建立一個可以重復使用的類,用于與一些彼此之間沒有太大關聯的一些類,包括一些可能在將來引進的類一起工作,這些源類不一定有一致的接口。
-
3、通過接口轉換,將一個類插入另一個類系中。(比如老虎和飛禽,現在多了一個飛虎,在不增加實體的需求下,增加一個適配器,在里面包容一個虎對象,實現飛的接口。)
優點:
-
促進代碼重用:通過適配器,原本不兼容的接口可以協同工作,提高了現有代碼的重用性。
提高透明性:客戶端代碼通過適配器與目標接口交互,而不需要直接依賴原有接口,這樣即便接口發生變化,客戶端代碼也無需改動。 -
靈活性:在系統引入新技術或者第三方庫時,可以通過適配器模式將其融入現有系統中,而不影響其他部分的代碼。
缺點: -
系統復雜性增加:引入適配器模式會增加系統中的類的數量,有時候可能會使得系統結構變得復雜。
-
過多使用可能導致混亂:如果在一個系統中大量使用適配器模式,可能會引起接口和實現的混亂,從而降低代碼的可讀性和可維護性。
-
性能開銷:每次調用都需要通過適配器進行轉換,這可能會帶來一定的性能開銷,尤其是在高性能要求的系統中需要特別注意。
源碼中應用
Spring MVC中廣泛使用了適配器模式,它用于將不同類型的Controller適配到統一的請求處理流程中。
在Spring MVC框架中,DispatcherServlet作為中心調度器負責處理所有的HTTP請求,但它并不直接執行請求處理方法,這項工作由HandlerAdapter來完成。HandlerAdapter在這里起到了適配器的作用,它將Controller(需要適配的類)適配到統一的接口上,以便DispatcherServlet可以透明地調用任何類型的Controller處理方法。
以下是適配器模式在Spring MVC中的應用細節:
- 定義適配器接口:定義一個HandlerAdapter接口,包含兩個主要方法——supports()用來判斷適配器是否支持對應的Controller,handle()用來執行Controller中的處理方法。
public interface HandlerAdapter {/***給定一個處理程序實例,返回此{@code HandlerAdapter}*可以支持它。典型的HandlerAdapters將根據處理程序做出決定類型HandlerAdapters通常每個只支持一種處理程序類型。*/boolean supports(Object handler);/***使用給定的處理程序來處理此請求。*/@NullableModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;/***與HttpServlet的{@code getLastModified}方法的合約相同。*/@Deprecatedlong getLastModified(HttpServletRequest request, Object handler);}
- 實現適配器:對于每種類型的Controller,提供相應的HandlerAdapter實現類。例如,HttpRequestHandlerAdapter用于適配HttpRequestHandler類型的處理器。
public class HttpRequestHandlerAdapter implements HandlerAdapter {@Overridepublic boolean supports(Object handler) {return (handler instanceof HttpRequestHandler);}@Override@Nullablepublic ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {((HttpRequestHandler) handler).handleRequest(request, response);return null;}@Override@SuppressWarnings("deprecation")public long getLastModified(HttpServletRequest request, Object handler) {if (handler instanceof LastModified) {return ((LastModified) handler).getLastModified(request);}return -1L;}}
- 存放適配器實例:Spring容器啟動時,會將所有定義好的HandlerAdapter實現類實例存放在一個List集合中供DispatcherServlet使用。
private void initHandlerAdapters(ApplicationContext context) {this.handlerAdapters = null;if (this.detectAllHandlerAdapters) {// 在ApplicationContext中查找所有HandlerAdapterMap<String, HandlerAdapter> matchingBeans =BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);if (!matchingBeans.isEmpty()) {this.handlerAdapters = new ArrayList<>(matchingBeans.values());// 排序HandlerAdapters AnnotationAwareOrderComparator.sort(this.handlerAdapters);}}else {try {HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);this.handlerAdapters = Collections.singletonList(ha);}catch (NoSuchBeanDefinitionException ex) {// 不處理,并添加默認的HandlerAdapters }}// 通過注冊,確保至少有一個HandlerAdapterif (this.handlerAdapters == null) {this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);if (logger.isTraceEnabled()) {logger.trace("No HandlerAdapters declared for servlet '" + getServletName() +"': using default strategies from DispatcherServlet.properties");}}}
- 選擇適配器:當請求到達時,DispatcherServlet會根據Handler的類型找到對應的HandlerAdapter。這個過程通常通過遍歷HandlerAdapter列表并使用supports()方法來確定。
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {if (this.handlerAdapters != null) {for (HandlerAdapter adapter : this.handlerAdapters) {if (adapter.supports(handler)) {return adapter;}}}throw new ServletException("No adapter for handler [" + handler +"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");}
- 處理請求:一旦找到了合適的HandlerAdapter,就會調用其handle()方法來執行Controller中的請求處理方法,并返回ModelAndView對象。
總的來說,適配器模式在Spring MVC中起到了至關重要的作用,它使得框架能夠靈活地處理各種類型的Controller而無需修改DispatcherServlet的內部邏輯。這種設計提高了代碼的可復用性和擴展性,同時遵循了設計模式中的開閉原則——對擴展開放,對修改關閉。