Gof 原文
Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatibleinterfaces.
它的使用使得两个不相关的接口可以一起工作。连接这些不相关接口的对象称为Adapter。 two unrelated interfaces can work together. The object that joins these unrelated interface is called an Adapter.
在软件开发中,基本上任何问题都可以通过增加一个中间层来解决。适配器模式其实就是一个中间层。综上,适配器模式起着转化/委托的作用,将一种接口转化为另一种符合需求的接口。就是借花献佛,用别人的功能做自己的事。就好比现在很多销售模式,你可以没有货源,没有售后,你只要买的出去货,工厂全给你负责了。
适配器模式适用于以下业务场景。
(1)已经存在的类,它的方法和需求不匹配(方法结果相同或相似)的情况。
(2)适配器模式不是软件设计阶段考虑的设计模式,是随着软件维护,由于不同产品、不同厂家造成功能类似而接口不相同情况下的解决方案,有种亡羊补牢的感觉。
适配器模式一般包含3个角色。 (1)目标角色(ITarget):也就是我们期望的接口。 (3)适配器(Adapter):将源角色(Adaptee)转化为目标角色(ITarget)的类实例。 (2)源角色(Adaptee):存在于系统中,是指内容满足客户需求但接口不匹配的接口实例。
适配器模式有3种形式:
- 类适配器、
- Class Adapter – This form uses java inheritance and extends the source interface, in our case Socket class.
- 对象适配器、
- Object Adapter – This form uses Java Composition and adapter contains the source object.
- 接口适配器:如果我们要实现的接口方法太多,而我们只需要用几个,都实现会很麻烦,所以引出了接口适配器,具体看下面例子
适配器模式与策略模式好像区别不大?适配器模式主要解决的是功能兼容问题,单场景适配大家可能不会和策略模式对比,但复杂场景适配大家就很容易混淆.
POJO
public class A1_Volt {
private int volts;
public A1_Volt(int v) {
this.volts = v;
}
public int getVolts() {
return volts;
}
public void setVolts(int volts) {
this.volts = volts;
}
}
使得如下两个不相关
的 接口/类 可以一起工作
public class A2_Socket {
public A1_Volt getVolt(){
return new A1_Volt(120);
}
}
public interface A3_SocketAdapter {
public A1_Volt get120Volt();
public A1_Volt get12Volt();
public A1_Volt get3Volt();
}
Class Adapter Implementation
public class A4_SocketClassAdapterImpl extends A2_Socket implements A3_SocketAdapter{
@Override
public A1_Volt get120Volt() {
return getVolt();
}
@Override
public A1_Volt get12Volt() {
A1_Volt v= getVolt();
return convertVolt(v,10);
}
@Override
public A1_Volt get3Volt() {
A1_Volt v= getVolt();
return convertVolt(v,40);
}
private A1_Volt convertVolt(A1_Volt v, int i) {
return new A1_Volt(v.getVolts()/i);
}
}
Object Adapter Implementation
public class A5_SocketObjectAdapterImpl implements A3_SocketAdapter{
private A2_Socket sock = new A2_Socket();
@Override
public A1_Volt get120Volt() {
return sock.getVolt();
}
@Override
public A1_Volt get12Volt() {
A1_Volt v= sock.getVolt();
return convertVolt(v,10);
}
@Override
public A1_Volt get3Volt() {
A1_Volt v= sock.getVolt();
return convertVolt(v,40);
}
private A1_Volt convertVolt(A1_Volt v, int i) {
return new A1_Volt(v.getVolts()/i);
}
}
测试,还配和了工厂模式
@Test
public void testObjectAdapter() {
A3_SocketAdapter sockAdapter = new A5_SocketObjectAdapterImpl();
A1_Volt v3 = getVolt(sockAdapter, 3);
A1_Volt v12 = getVolt(sockAdapter, 12);
A1_Volt v120 = getVolt(sockAdapter, 120);
System.out.println("v3 volts using Object Adapter=" + v3.getVolts());
System.out.println("v12 volts using Object Adapter=" + v12.getVolts());
System.out.println("v120 volts using Object Adapter=" + v120.getVolts());
}
@Test
public void testClassAdapter() {
A3_SocketAdapter sockAdapter = new A4_SocketClassAdapterImpl();
A1_Volt v3 = getVolt(sockAdapter, 3);
A1_Volt v12 = getVolt(sockAdapter, 12);
A1_Volt v120 = getVolt(sockAdapter, 120);
System.out.println("v3 volts using Class Adapter=" + v3.getVolts());
System.out.println("v12 volts using Class Adapter=" + v12.getVolts());
System.out.println("v120 volts using Class Adapter=" + v120.getVolts());
}
private static A1_Volt getVolt(A3_SocketAdapter sockAdapter, int i) {
switch (i) {
case 3:
return sockAdapter.get3Volt();
case 12:
return sockAdapter.get12Volt();
case 120:
return sockAdapter.get120Volt();
default:
return sockAdapter.get120Volt();
}
}
v3 volts using Class Adapter=3
v12 volts using Class Adapter=12
v120 volts using Class Adapter=120
v3 volts using Object Adapter=3
v12 volts using Object Adapter=12
v120 volts using Object Adapter=120
接口适配器
假如接口有这么多方法,但是我只用第一个方法,其余也实现会很麻烦
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");
}
}
以上我觉的更像是用了简单工厂模式
HandlerAdapter更像是用了适配器模式
适配器模式与装饰器模式的区别
适配器模式和装饰器模式都是包装器模式(Wrapper Pattern)
Process [ 美 /prəˈses;ˈprɑːses/ ] 过程
Oriented [ 美 /ˈɔːrientɪd/] 以……为方向的
Programming [美 /ˈproʊɡræmɪŋ/] [计] 程序编制
- POP–面向过程编程(Process Oriented Programming);
- OOP–面向对象编程(Object Oriented Programming);
- AOP–面向方面编程(Aspect Oriented Programming); 理解POP,OOP,AOP之间的关系