Gof 原文
Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatibleinterfaces.
目录标题
[Q&A] 适配器模式适用于哪些业务场景?
1、已经存在的类,它的方法和需求不匹配(但是方法结果相同或相似)的情况。在软件开发中,基本上任何问题都可以通过增加一个中间层来解决。
2、适配器模式不是软件设计阶段考虑的设计模式,是随着软件维护,由于不同产品、不同厂家造成功能类似而接口不相同情况下的解决方案,有种亡羊补牢的感觉。
适配器模式有3种形式
1・Class Adapter – This form uses java inheritance and extends the source interface, in our case Socket class.
2・Object Adapter – This form uses Java Composition and adapter contains the source object.
3・接口适配器:如果我们要实现的接口方法太多,而我们只需要用几个,都实现会很麻烦,所以引出了接口适配器,具体看下面例子
Class Adapter :Using inheritance for adapter pattern
public interface ISocketAdapter {
public Volt get120Volt();
public Volt get12Volt();
public Volt get3Volt();
}
public class Socket {
public Volt getVolt(){
return new Volt(120);
}
}
//Using inheritance for adapter pattern
public class SocketInheritanceAdapter extends Socket implements ISocketAdapter {
@Override
public Volt get120Volt() {
return getVolt();
}
@Override
public Volt get12Volt() {
Volt v = getVolt();
return convertVolt(v, 10);
}
@Override
public Volt get3Volt() {
Volt v = getVolt();
return convertVolt(v, 40);
}
private Volt convertVolt(Volt v, int i) {
return new Volt(v.getVoltValue() / i);
}
}
Object Adapter :Using Composition for adapter pattern
public class SocketCompositionAdapter implements ISocketAdapter {
//Using Composition for adapter pattern
private final Socket sock = new Socket();
@Override
public Volt get120Volt() {
return sock.getVolt();
}
@Override
public Volt get12Volt() {
Volt v= sock.getVolt();
return convertVolt(v,10);
}
@Override
public Volt get3Volt() {
Volt v= sock.getVolt();
return convertVolt(v,40);
}
private Volt convertVolt(Volt v, int i) {
return new Volt(v.getVoltValue()/i);
}
}
接口适配器
假如接口有这么多方法,但是我只用第一个方法,其余也实现会很麻烦
public interface DCOutput {
int output5V();
int output9V();
int output12V();
int output24V();
}
这里抽象类其实就写了空方法,等着子类去实现需要的方法。
public abstract class PowerAdapter implements DCOutput{
protected AC220 mAC220;
public PowerAdapter(AC220 ac220){
this.mAC220 = ac220;
}
@Override
public int output5V() {
return 0;
}
@Override
public int output9V() {
return 0;
}
@Override
public int output12V() {
return 0;
}
@Override
public int output24V() {
return 0;
}
}
子类继承就可以选择性的重写父类的方法了,就不需要实现接口所有的方法了
package com.demo.adapter.interfaceadapter;
import com.demo.adapter.classadapter.AC220;
/
* Created by italkbb on 2018/1/24.
*/
public class Power5VAdapter extends PowerAdapter {
public Power5VAdapter(AC220 ac220) {
super(ac220);
}
@Override
public int output5V() {
int output = 0;
if (mAC220 != null) {
output = mAC220.output220V() / 44;
}
return output;
}
}
适配器模式应用
适配器模式在Spring源码中的应用
在Spring中,适配器模式应用得非常广泛,例如Spring AOP中的AdvisorAdapter类,
它有3个实现类:MethodBeforeAdviceAdapter
、AfterReturningAdviceAdapter
和ThrowsAdviceAdapter
。
先来看顶层接口AdvisorAdapter
。
public interface AdvisorAdapter {
boolean supportsAdvice(Advice advice);
MethodInterceptor getInterceptor(Advisor advisor);
}
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof MethodBeforeAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
return new MethodBeforeAdviceInterceptor(advice);
}
}
Spring会根据不同的AOP配置来确定使用对应的Advice,与策略模式不同的是,一个方法可以同时拥有多个Advice。
适配器模式在SpringMVC源码中的应用
public class DispatcherServlet extends FrameworkServlet {
...
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
...
// 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");
}
}
适配器模式与装饰器模式的区别
适配器模式和装饰器模式都是包装器模式(Wrapper Pattern)
适配器模式与策略模式好像区别不大?适配器模式主要解决的是功能兼容问题,单场景适配大家可能不会和策略模式对比,但复杂场景适配大家就很容易混淆.