设计模式-适配器模式

1、概述

结构型模式

1. 适配器模式(Adapter Pattern)将某个类的接口转化为客户端期望的另一个接口表示,主要的目的是兼容性,让原本不匹配不能一起工作的两个类可以协同工作,其名为包装器(Wrapper)
2. 适配器模式属于结构型模式
3. 主要分为三类:类适配器模式、对象适配器模式、接口适配器模式
4. 工作原理就是:用户调用适配器转换出来的接口,适配器在调用被适配类的相关接口,从而完成适配

2、优缺点

优点:

    安全可靠:封装了旧接口,对客户端透明,客户端代码无需修改。
    提高复用性:可以复用不兼容的类;可以对不同的类无需修改,就可以进行组合。
    扩展性好:在应用程序开发过程中,可以增加新的适配器和被适配对象。

缺点:

    过多的适配器会导致系统结构复杂。
    如果适配器没有实现好,可能会拖慢整个系统的性能。
    滥用适配器模式会导致系统设计紊乱

3、实现方式

类适配器


//测试类
public class Test {
    public static void main(String[] args) {
        //类适配器使得代码逻辑混乱
        //这种情况下仿佛Adapter是一种110V的美国供电器可以直接使用不需要其他信息
        //具体可以和对象适配器对比以下
        new Adapter().chargeBy220V();
    }
}

//客户期望的接口——220V的电压充电
interface Target {
    void chargeBy220V();
}

//现有接口——只能通过110V电压充电
interface Adaptee {
    void chargeBy110V();
}

//现有接口的具体实现类,美国供电器——通过110V电压供电
class americanCharger implements Adaptee {
    @Override
    public void chargeBy110V() {
        System.out.println("110V");
    }
}

//类适配器,通过继承现有接口来完成对现有接口的扩展
class Adapter extends americanCharger implements Target {
    @Override
    public void chargeBy220V() {
        super.chargeBy110V();//现有功能
        System.out.println("220V");//对现有功能扩展
    }
}

//输出
/*
110V
220V
*/

对象适配器


//测试类
public class Test {
    public static void main(String[] args) {
        //现在我们有一个美国110V供电站,但我们无法使用
        Adaptee adaptee = new americanCharger();

        //我们将这个供电器交给适配器,适配器转换为220V供电器
        Adapter adapter = new Adapter(adaptee);

        //接下来我们通过适配器充电就好了
        adapter.chargeBy220V();        
    }
}

//客户期望的接口——220V的电压充电
interface Target {
    void chargeBy220V();
}

//现有接口——只能通过110V电压充电
interface Adaptee {
    void chargeBy110V();
}

//现有接口的具体实现类,美国供电器——通过110V电压供电
class americanCharger implements Adaptee {
    @Override
    public void chargeBy110V() {
        System.out.println("110V");
    }
}

//类适配器,通过继承现有接口来完成对现有接口的扩展,使得能够110V供电
class Adapter implements Target {
    Adaptee adaptee;//持有现有接口具体实现对象的引用

    public Adapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    @Override
    public void chargeBy220V() {
        adaptee.chargeBy110V();//该对象的现有功能
        System.out.println("220V");//对现有功能扩展
    }
}

接口适配器


//测试类
public class Test {
    public static void main(String[] args) {
        //现在我们有一个美国110V供电站,但我们无法使用
        Adaptee adaptee = new americanCharger();

        //我们将这个供电站交给中国制造的适配器
        Adapter adapter = new ChinaMakeAdapter(adaptee);

        //接下来我们通过适配器充电就好了
        adapter.chargeBy220V();
    }
}

//客户期望的接口——220V的电压充电
interface Target {
    void chargeBy220V();
}

//现有接口——只能通过110V电压充电
interface Adaptee {
    void chargeBy110V();
}

//现有接口的具体实现类,美国供电器——通过110V电压供电
class americanCharger implements Adaptee {
    @Override
    public void chargeBy110V() {
        System.out.println("110V");
    }
}

//抽象类适配器,通过继承现有接口来完成对现有接口的扩展
abstract class Adapter implements Target {
    Adaptee adaptee;//持有现有接口具体实现对象的引用

    public Adapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }
}

//中国自制
class ChinaMakeAdapter extends Adapter {

    public ChinaMakeAdapter(Adaptee adaptee) {
        super(adaptee);
    }

    @Override
    public void chargeBy220V() {
        adaptee.chargeBy110V();//该对象的现有功能
        System.out.println("220V");//对现有功能扩展
    }
}

//测试类
public class Test {
    public static void main(String[] args) {
        //我们去美国,酒店里有一个美国110V充电站,我们需要220V的电压
        B b = new AmericanCharger();
        //我们将这个充电站交给适配器以获取220V电压充电
        Adapter adapter1 = new Adapter(b);
        //接下来我们通过适配器充电就好了
        adapter1.chargeBy220V();

        System.out.println();

        //美国人来中国,酒店里有一个中国220V充电站,但他需要110V的电压
        A a = new ChinaCharger();
        //将这个充电站交给适配器以获取110V电压充电
        Adapter adapter2 = new Adapter(a);
        //接下来我们通过适配器充电就好了
        adapter2.chargeBy110V();
    }
}

//接口A——220V的电压供电
interface A {
    void chargeBy220V();
}


//接口A的具体实现类,中国供电器——通过220V电压供电
class ChinaCharger implements A {
    @Override
    public void chargeBy220V() {
        System.out.println("220V");
    }
}

//接口B——110V电压供电
interface B {
    void chargeBy110V();
}

//接口B的具体实现类,美国供电器——通过110V电压供电
class AmericanCharger implements B {
    @Override
    public void chargeBy110V() {
        System.out.println("110V");
    }
}

//双向适配器
class Adapter implements A, B {
    A a; //220V充电
    B b; //110V充电


    public Adapter(A a) {
        this.a = a;
    }

    public Adapter(B b) {
        this.b = b;
    }

    @Override
    public void chargeBy220V() {
        b.chargeBy110V(); //当前接口
        System.out.println("220V");//适配目标接口
    }

    @Override
    public void chargeBy110V() {
        a.chargeBy220V();//当前接口
        System.out.println("110V");
    }
}

/*
110V
220V

220V
110V
*/

4、应用场景

生活中

1. 电压转换器:不同国家的电压规格各异,同样功率的电器在不同的地方工作时需要不同的电压,电压转换器作为适配器,将不同电压转换成电器使用标准电压。

2. 耳机转接头:有些手机没有耳机插口,需要使用转接头适配器,将耳机转换为手机支持的接口,实现对不同的耳机兼容。
3. 显示器转接头,如VGA-HDMI;电脑数据线转接头,如typeC-usb

程序中

1. JDBC驱动程序:不同的数据库提供商实现了不同的JDBC驱动接口,使用适配器模式可以将这些不同的接口适配为标准的JDBC接口,提高应用程序的可移植性。

2. 日志框架:Java中有多个常用的日志框架,如Log4j、SLF4J等,不同的日志框架提供的API不同,使用适配器模式可以将这些不同的API适配为一个统一的接口,方便再程序中进行日志记录和管理。

3. 第三方库或SDK:在使用第三方库或 SDK 时,可能由于它们实现的 API 不同而导致应用程序复杂,使用适配器模式可以将不同的 API 适配为统一的接口,简化应用程序的调用。
This entry was posted in 应用, 设计模式. Bookmark the permalink.