适配器模式又叫做变压器模式,它的功能是将一个类的接口变成客户端所期望的另一个接口,从而使原本接口不匹配而导致无法在一起工作的两个类能够一起工作。属于结构型设计模式。
适配器模式的使用场景
1、已经存在的类,它的方法和需求不匹配的情况
2、适配器模式不是软件设计阶段考虑的设计模式,是随着软件维护,由于不同产品、不同厂家造成功能类似而接口不相同情况下的解决方案。(类似于一种后期的修改方案,符合开闭原则,主要是解决兼容问题)
类适配器 不满住最小知道原则
对象适配器 通过构造方法传入原角色符合最小知道原则
接口适配器 违背单一职责原则和接口隔离原则
优点:
1、能提高类的透明性和复用,现有的类复用但不需要改变
2、目标类和适配器类解耦,提高程序的扩展性
3、在很多业务场景中符合开闭原则
缺点:
1、增加了类的复杂性
2、增加代码的阅读难度,降低可读性,过多的使用适配器会使系统代码变得凌乱
适配器模式的类图:
PassportService类实现一个注册到登录的过程(登录有很多种的实现,可以用qq登录、微信登录、手机短信验证登录等等),如下图通过增加一个第三方注册登录的接口和一个第三方注册登录的接口实现类,通过一个abstractAdapter类来完成登录方式的共用方法且继承一个登录的适配器,然后各种登录模块的继承实现;
核心代码:
PassportForThirdAdapter类继承IpassportForThird接口
public ResultMsg loginForTelphone(String phone, String code) {
return processLogin(phone, LoginForTelAdapter.class);
}
//核心实现通过传入类(类必须继承ILoginAdapter),判断是否支持改适配器,如果为true则进行执行登录
private ResultMsg processLogin(String id,Class<? extends ILoginAdapter> clazz){
try {
ILoginAdapter adapter = clazz.newInstance();
if (adapter.support(adapter)){
return adapter.login(id,adapter);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//登录实现继承登录抽象接口
public class LoginForTelAdapter extends AbstraceAdapter{
public boolean support(Object adapter) {
return adapter instanceof LoginForTelAdapter;
}
public ResultMsg login(String id, Object adapter) {
return super.loginForRegist(id,null);
}
}
//抽象方法继承注册登录类继承登录适配器,通过该适配器判断是否支持第三方登录,然后进行调用PassportService 的注册和登录接口
public abstract class AbstraceAdapter extends PassportService implements ILoginAdapter {
protected ResultMsg loginForRegist(String username, String password){
if(null == password){
password = "thirdPassword";
}
super.regist(username,password);
return super.login(username,password);
}
}
在Spring源码中也有广泛的应用:AdvisorAdapter 、DispatcherServlet等
public interface AdvisorAdapter {
boolean supportsAdvice(Advice var1);
MethodInterceptor getInterceptor(Advisor var1);
}
class AfterReturningAdviceAdapter implements AdvisorAdapter, Serializable {
AfterReturningAdviceAdapter() {
}
public boolean supportsAdvice(Advice advice) {
return advice instanceof AfterReturningAdvice;
}
public MethodInterceptor getInterceptor(Advisor advisor) {
AfterReturningAdvice advice = (AfterReturningAdvice)advisor.getAdvice();
return new AfterReturningAdviceInterceptor(advice);
}
}
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
try {
ModelAndView mv = null;
Object dispatchException = null;
try {
processedRequest = this.checkMultipart(request);
multipartRequestParsed = processedRequest != request;
mappedHandler = this.getHandler(processedRequest);
if (mappedHandler == null) {
this.noHandlerFound(processedRequest, response);
return;
}
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
return;
}
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
this.applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception var20) {
dispatchException = var20;
} catch (Throwable var21) {
dispatchException = new NestedServletException("Handler dispatch failed", var21);
}
this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
} catch (Exception var22) {
this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
} catch (Throwable var23) {
this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
}
} finally {
if (asyncManager.isConcurrentHandlingStarted()) {
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
} else if (multipartRequestParsed) {
this.cleanupMultipart(processedRequest);
}
}
}