设计模式之适配器模式

1. 基本介绍

  • 定义

    将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作

  • 主要解决

    主要解决在软件系统中,常常要将一些“现存的对象”放到新环境中,而新环境要求的接口是现对象不能满足的。

  • 何时使用

    1. 系统需要使用现有的类,而此类的接口不符合系统的需要。
    2. 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作,这些源类不一定有一致的接口。
    3. 通过接口转换,将一个类插入另一个类系中。
  • 如何解决

    继承依赖(推荐使用依赖)

  • 关键代码

    适配器继承或依赖已有的对象,实现想要的目标接口。

  • 优点

    1. 可以让任何两个没有关联的类一起运行。
    2. 提高了类的复用。
    3. 增加了类的透明度。
    4. 灵活性好。
  • 缺点

    1. 过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是A接口,其实内部被适配成了B接口的实现,一个系统如果出现太多这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
    2. 由于JAVA至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。
  • 使用场景

    有动机地修改一个正常运行的系统的接口,这时应该考虑使用适配器模式。

  • 注意事项

    适配器不是在详细设计时添加的,而是解决正在服役的项目的问题。

  • 应用实例

    1. 美国电器110V,中国电器220V,就要有一个适配器将110V转换为220V。

    2. JDK 1.1提供了Enumeration接口,而在1.2中提供了Iterator接口,想要使用1.2的JDK,则要将以前系统的Enumeration接口转化为Iterator接口,这时就需要适配器模式。

    3. java中的JDBC。JDBC给出一个客户端通用的抽象接口,每一个具体数据库厂商就会去开发JDBC驱动,就是一个介于JDBC接口和数据库引擎接口之间的适配器软件。

      在这里插入图片描述

2. 分类及使用

  • 基本介绍
    • 适配器模式是作为两个不兼容的接口之间的桥梁。
    • 适配器模式属于结构型模式
    • 主要分为三类:类适配器模式对象适配器模式接口适配器模式
  • 结构角色
    • 目标接口(Target):当前系统业务所期待的接口,它可以是抽象类或接口
    • 适配者类(Adaptee):它是被访问和适配的现存组件库中的组件接口。
    • 适配器类(Adapter):它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标借口,让客户按目标接口的格式访问适配者。

2.1 类适配器模式

类适配器模式的实现是让适配器类继承适配者类、实现目标接口,在重写目标接口的方法时,内部调用的其实是适配者类的方法。

结构图:

在这里插入图片描述

目标接口

/**
 * 目标接口
 */
public interface Target {
    public void request();
}

适配者类

/**
 * 适配者类
 */
public class Adaptee {
    public void specificRequest(){
        System.out.println("适配者中的业务代码被调用");
    }
}

类适配器类

/**
 * 类适配器类
 */
public class ClassAdapdter extends Adaptee implements Target{
    @Override
    public void request() {
        super.specificRequest();
    }
}

测试类(客户端)

@Test
public void test01(){
    Target target = new ClassAdapdter();
    target.request();
}

结果

适配者中的业务代码被调用
  • 类适配器模式优点
    • 由于适配器类是适配者类的子类,因此可以在适配器类中置换一些适配者的方法,使得适配器的灵活性更强。
  • 类适配器模式缺点
    • 对于Java等不支持多继承的语言,一次最多只能适配一个适配者类,不能同时适配多个适配者。
    • 适配者类的方法在适配器类中会全部暴露出来,增加了使用的成本。

2.2 对象适配器模式

对象适配器模式不同于类适配器的地方在于对象适配器模式是采取组合的方式实现适配的,让适配器类实现目标接口,但是并不继承适配者类,在适配器内部定义一个适配者实例,在实现目标接口的方法时调用适配者实例的方法。

结构图

在这里插入图片描述

目标接口

/**
 * 目标接口
 */
public interface Target {
    public void request();
}

适配者类

/**
 * 适配者类
 */
public class Adaptee {
    public void specificRequest(){
        System.out.println("适配者中的业务代码被调用");
    }
}

对象适配器类

/**
 * 对象适配器类
 */
public class ObjectAdapter implements Target{

    private Adaptee adaptee;

    public ObjectAdapter(Adaptee adaptee){
        this.adaptee = new Adaptee();
    }

    @Override
    public void request() {
        adaptee.specificRequest();
    }
}

测试类(客户端)

    @Test
    public void test02(){
        Adaptee adaptee = new Adaptee();
        Target target = new ObjectAdapter(adaptee);
        target.request();
    }

结果

适配者中的业务代码被调用
  • 对象适配器模式的优点
    • 一个对象适配器可以把多个不同的适配者适配到同一个目标。
    • 可以适配适配者的子类。
    • 解决了适配器类必须继承适配者类的缺陷。
    • 使用成本更低、更灵活。
  • 对象适配器模式的缺点
    • 更换适配器的实现过程比较复杂

2.3 接口适配器模式

当我们只是想使用接口中的其中一部分方法而不是全部方法时,我们可以使用接口适配器模式。接口适配器模式是让适配器类实现目标接口的所有方法,但是方法内部其实什么也没有,当我们只需要使用一部分时,使用适配器类的子类重写我们需要的方法即可。

结构图:

在这里插入图片描述

目标接口

/**
 * 目标接口
 */
public interface Target {
    public void method01();
    public void method02();
    public void method03();
    public void method04();
}

接口适配器类

/**
 * 接口适配器类
 */
public class InterfaceAdapter implements Target {

    @Override
    public void method01() {

    }

    @Override
    public void method02() {

    }

    @Override
    public void method03() {

    }

    @Override
    public void method04() {

    }
}

接口适配器类的子类

/**
 * 接口适配器类子类
 * 假如只需要重写method01()、method02()方法
 */
public class InterfaceAdapterSon extends InterfaceAdapter{

    @Override
    public void method01() {
        System.out.println("接口适配器类的子类重写method01()方法");
    }

    @Override
    public void method02() {
        System.out.println("接口适配器类的子类重写method02()方法");
    }
}

测试类(客户端)

@Test
public void test01(){
    Target target = new InterfaceAdapterSon();
    target.method01();
    target.method02();
}

结果

接口适配器类的子类重写method01()方法
接口适配器类的子类重写method02()方法

3. 总结

  • 适配器模式的优点

    • 将目标类和适配者类解耦,通过引入一个适配器类来使用现有的适配者类,无需修改原有代码(符合开闭原则)。
    • 通过适配器,客户端可以调用同一接口,具体的实现业务封装在适配者类中,对于客户端而言是透明的。
    • 复用了现存的类,解决了现存类和复用环境要求不一致的问题。提高了适配者类的复用性,同一个适配者类可以在多个不同的系统中复用。
  • 应用场景

    • 系统想要使用现有的类,而这些类的接口不符合系统的接口。
    • 两个类所做的事相同或相似,但是具有不同接口的时候。
    • 使用第三方组件,组件接口定义和自己定义的不同,不希望修改自己的接口,但是要使用第三方组件的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值