06 适配器模式(Adapter Design Pattern)

一句话概括:有点数据类型转化辅助类的意思。

适配器模式将某个类的接口转换成客户端期望的另一个接口表示,主的目的是兼容性,让原本因接口不匹配不能一起工作的两个类可以协同工作。其别名为包装器(Wrapper)。

需要被适配的类、接口、对象(我们有的),简称 src(source)

最终需要的输出(我们想要的),简称 dst (destination,即Target)

适配器称之为 Adapter 。

一句话描述适配器模式的感觉: src->Adapter->dst, 即src以某种形式(三种形式分别对应三种适配器模式)给到Adapter里,最终转化成了dst。

适配器设计模式的一个非常实际的例子是电源适配器。 手机电池充电电压是3伏,但正常插座可以产生120V(美国)、240V(印度)、220V(中国)等。 因此,电源适配器可作为移动充电器和墙上插座之间的适配器。

接下来我们尝试使用适配器模式实现多适配器。

//电压
public class Volt {

    private int volts;

    public Volt(int v){
        this.volts=v;
    }

    public int getVolts() {
        return volts;
    }

    public void setVolts(int volts) {
        this.volts = volts;
    }

}
//墙上的插座,输出120V电压
public class Socket {

    public Volt getVolt(){
        return new Volt(120);
    }
}

现在我们要构建一个可产生3伏,12伏和默认120伏的适配器。所以首先我们创建一个适配器接口。

public interface SocketAdapter {

    public Volt get120Volt();

    public Volt get12Volt();

    public Volt get3Volt();
}

Two Way Adapter Pattern

在实现适配器模式时,有两种方法 - 类适配器和对象适配器 - 但是这两种方法都会产生相同的结果。

  • 类适配器(Class Adapter) - 这种形式使用JAVA继承(java inheritance)并扩展了原始接口,在我们的例子中是Socket类。
  • 对象适配器(Object Adapter) - 此种形式使用JAVA组合(Java Composition)并且适配器包含原始对象。

Adapter Design Pattern – Class Adapter

//Using inheritance for adapter pattern
public class SocketClassAdapterImpl extends Socket implements SocketAdapter{

    @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.getVolts()/i);
    }

}

Adapter Design Pattern – Object Adapter Implementation

public class SocketObjectAdapterImpl implements SocketAdapter{

    //Using Composition for adapter pattern
    private 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.getVolts()/i);
    }
}

注意两种适配器的实现几乎相同,他们都继承了SocketAdapter接口。适配器接口也可以是个抽象类。

下面是测试代码:

public class AdapterPatternTest {

    public static void main(String[] args) {

        testClassAdapter();
        testObjectAdapter();
    }

    private static void testObjectAdapter() {
        SocketAdapter sockAdapter = new SocketObjectAdapterImpl();
        Volt v3 = getVolt(sockAdapter,3);
        Volt v12 = getVolt(sockAdapter,12);
        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());
    }

    private static void testClassAdapter() {
        SocketAdapter sockAdapter = new SocketClassAdapterImpl();
        Volt v3 = getVolt(sockAdapter,3);
        Volt v12 = getVolt(sockAdapter,12);
        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 Volt getVolt(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

Adapter Design Pattern Example in JDK

在JDK中可以很容易找出几个简单的适配器模式的应用

java.util.Arrays#asList()
java.io.InputStreamReader(InputStream) (returns a Reader)
java.io.OutputStreamWriter(OutputStream) (returns a Writer)

使用场景

  • 系统需要使用现有的类,而这些类的接口不符合系统的需要。
  • 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。
  • 需要一个统一的输出接口,而输入端的类型不可预知。

你可能感兴趣的:(06 适配器模式(Adapter Design Pattern))