一,適配器模式
適配器模式:
- 將一個類的接口轉換成另一個類的接口,讓原本不兼容的兩個類可以兼容;
- 使用者看不到被適配者,實現解耦,用戶調用適配器轉化之後的接口,適配器再去調用被適配的相關接口;
- 常見有三種分類:類適配器,對象適配器,接口適配器;
二,原理類圖
意圖: 將一個類的接口轉換成客戶希望的另外一個接口。Adapter 模式使得原本由於接口不兼容而不能一起工作的那些類可以一起工作。
適用性:
- 你想使用一個已經存在的類,而它的接口不符合你的需求。
- 你想創建一個可以複用的類,該類可以與其他不相關的類或不可預見的類(即那些接口可能不一定兼容的類)協同工作。
- (僅適用於對象Adapter )你想使用一些已經存在的子類,但是不可能對每一個都進行子類化以匹配它們的接口。對象適配器可以適配它的父類接口。
三,實例
1,類適配器:
描述:
- adapter類,通過繼承src類,實現dst類接口,完成src到dst的適配;
- 由於java的單繼承,類適配器必須繼承,繼承上有一定的侷限性,但繼承之後的方法可以重寫也使得靈活性增強;
- 被適配類的方法會在適配器中暴露出來,增加了使用成本;
需要被適配的類
package com.neei.adapter.classAdapter;
/**
* @param
* @Author: AaNeei
* @Date: 2019/10/3 10:23
* @Description: src基類(被適配的類)
* @throws:
*/
public class Voltage220V {
private static final int VOLTAGE_220V = 220;
public int getVoltage220V() {
System.out.println("原始電壓:" + VOLTAGE_220V + "V");
return VOLTAGE_220V;
}
}
適配接口
package com.neei.adapter.classAdapter;
/**
* @param
* @Author: AaNeei
* @Date: 2019/10/3 10:26
* @Description: 適配接口
* @throws:
*/
public interface Voltage5V {
int getVoltage5V();
}
適配器
package com.neei.adapter.classAdapter;
/**
* @param
* @Author: AaNeei
* @Date: 2019/10/3 10:27
* @Description: 根據需要的適配類
* @throws:
*/
public class VoltageAdapter extends Voltage220V implements Voltage5V {
@Override
public int getVoltage5V() {
int srcV = getVoltage220V();
int dstV = srcV / 44;
return dstV;
}
}
適配
package com.neei.adapter.classAdapter;
/**
* @param
* @Author: AaNeei
* @Date: 2019/10/3 10:35
* @Description: 遊學網
* @throws:
*/
public class Phone {
public void change(Voltage5V v){
System.out.println(v.getVoltage5V()==5?"5V電壓可以充電":
v.getVoltage5V()+"V電壓不能充電");
}
}
調用
package com.neei.adapter.classAdapter;
/**
* @param
* @Author: AaNeei
* @Date: 2019/10/3 10:29
* @Description: 遊學網
* @throws:
*/
public class Client {
public static void main(String[] args) {
Phone phone = new Phone();
phone.change(new VoltageAdapter());
}
}
2,對象適配器:
描述: 根據合成複用原則,將類適配器的繼承方式轉換爲組合方式,讓adapter類持有src類,相對於類適配器靈活性更高;
適配器調整如下:
通過屬性方式注入src對象;
package com.neei.adapter.classAdapter;
/**
* @param
* @Author: AaNeei
* @Date: 2019/10/3 10:27
* @Description: 根據需要的適配類
* @throws:
*/
public class VoltageAdapter implements Voltage5V {
private Voltage220V voltage220V;
public VoltageAdapter(Voltage220V voltage220V) {
this.voltage220V = voltage220V;
}
@Override
public int getVoltage5V() {
int srcV = voltage220V.getVoltage220V();
int dstV = srcV / 44;
return dstV;
}
}
3,接口適配器:
描述: 當一個接口有N多個方法需要實現時,可以使用一個抽象類先實現該接口的所有方法(默認實現),然後在通過關聯到該抽象類去實現或重寫我們要使用的方法;
四,源碼分析
SpringMVC源碼中使用的適配器模式,如HandlerAdapter;
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.適配器方法
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
...
}
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
for (HandlerAdapter ha : this.handlerAdapters) {
if (logger.isTraceEnabled()) {
logger.trace("Testing handler adapter [" + ha + "]");
}
if (ha.supports(handler)) {
return ha;
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
public boolean supports(Object handler) {
return (handler instanceof Controller);
}