Java设计模式:适配器模式的三种形式(五)

简介: Java设计模式:适配器模式的三种形式(五)

一、什么是适配器模式

适配器模式(Adapter Pattern)的核心概念是将一个类的接口转换成客户期望的另一个接口,从而让原本接口不兼容的类能够合作无间。适配器模式通过引入一个适配器类来实现这种转换,适配器类通常持有源类(即被适配的类)的引用,并实现目标接口(即客户期望的接口)。客户端代码通过调用适配器类的方法来间接调用源类的方法,从而实现接口的适配。

角色概念

适配器模式的角色概念:

  1. 目标接口(Target):客户所期待的接口,也就是适配器需要实现的接口。
  2. 源类/源接口(Adaptee):已存在的类或者接口,其方法或者行为与客户所期待的接口不兼容,需要适配器来进行适配。
  3. 适配器(Adapter):适配器是适配器模式的核心,它是一个类,该类将源类/源接口的方法或行为转换为客户所期待的接口的方法或行为。适配器通过持有源类/源接口的引用,并在其实现的目标接口方法中调用源类/源接口的方法来实现适配。

使用场景

  • 当你想使用一个已经存在的类,但其接口不符合你的需求时,你可以使用适配器模式。
  • 当你想要创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作时,你可以使用适配器模式。例如,在Android开发中,Adapter就是一个典型的适配器模式的应用,它使得ListView等UI组件可以与各种数据源进行协作。
  • 当你需要一个统一的输出接口,而输入类型不可预知时,你可以使用适配器模式。这样,你可以通过适配器将各种输入类型转换为统一的输出接口。


二、适配器模式的三种形式

适配器模式主要分三种:类适配器模式、对象适配器模式、接口适配器模式(默认适配器模式)。

下面将给出代码,并简要说明它们的使用场景以及各自的优缺点。

1. 类适配器模式(Class Adapter Pattern)

代码
// 源类(Adaptee)
public class Adaptee {
    public void specificRequest() {
        System.out.println("源类特有请求");
    }
}

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

// 类适配器(继承源类,实现目标接口)
public class ClassAdapter extends Adaptee implements Target {
    @Override
    public void request() {
        specificRequest(); // 调用源类的方法
        System.out.println("类适配器对请求进行了适配");
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Target target = new ClassAdapter();
        target.request();
    }
}
使用场景

当你想将一个已经存在的类适配到一个不兼容的接口,并且这个类的方法在适配器中都会被用到时,可以使用类适配器模式。

优点
  • 适配器可以覆盖源类的方法,提供更灵活的行为控制。
  • 代码结构比较简单,只需继承源类和实现目标接口。
缺点
  • 由于Java不支持多重继承,如果源类已经是某个类的子类,则无法使用类适配器模式。
  • 适配器与源类紧密耦合,源类的任何改变都可能影响适配器。

2. 对象适配器模式(Object Adapter Pattern)

代码
// 源类(Adaptee,与类适配器模式中的相同)

// 目标接口(Target,与类适配器模式中的相同)

// 对象适配器(持有源类的引用,实现目标接口)
public class ObjectAdapter implements Target {
    private Adaptee adaptee;

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

    @Override
    public void request() {
        adaptee.specificRequest(); // 调用源类的方法
        System.out.println("对象适配器对请求进行了适配");
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Adaptee adaptee = new Adaptee();
        Target target = new ObjectAdapter(adaptee);
        target.request();
    }
}
使用场景

当你想将一个已经存在的类适配到一个不兼容的接口,但你不想使用继承或者源类的方法在适配器中不会被全部用到时,可以使用对象适配器模式。

优点
  • 适配器与源类的关系由继承变为关联,更加灵活。
  • 可以适配多个源类到同一个目标接口,只需在适配器中更换源类对象即可。
缺点
  • 需要额外创建适配器类来适配源类和目标接口。
  • 相比类适配器模式,对象适配器模式的性能可能略低,因为涉及到对象的创建和引用。

3. 接口适配器模式(Interface Adapter Pattern)

代码
// 目标接口(有很多方法)
public interface Target {
    void method1();
    void method2();
    // ... 其他方法
}

// 抽象适配器类(实现目标接口,提供所有方法的默认实现)
public abstract class AbstractAdapter implements Target {
    @Override
    public void method1() { /* 默认实现 */ }
    @Override
    public void method2() { /* 默认实现 */ }
    // ... 其他方法的默认实现
}

// 具体适配器类(继承抽象适配器类,重写需要的方法)
public class ConcreteAdapter extends AbstractAdapter {
    @Override
    public void method1() {
        // 实现具体功能
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Target adapter = new ConcreteAdapter();
        adapter.method1(); // 调用具体功能
        // adapter.method2(); 使用默认实现,如果需要的话
    }
}
使用场景

当一个接口有很多方法,但客户端只对其中的一部分方法感兴趣,或者想要提供一个只需要实现部分方法的默认实现时,可以使用接口适配器模式。

优点
  • 客户端可以只覆盖它感兴趣的方法,对于其他方法可以使用默认实现。
  • 减少了实现接口所需的工作量,因为大部分方法已经有了默认实现。
缺点
  • 如果需要为多个不相关的接口提供适配器,则可能需要为每个接口都创建一个抽象适配器和具体适配器,增加了系统的复杂性。
  • 当接口改变时,可能需要更新抽象适配器以提供新的默认实现。

三、注意事项

  • 适配器模式不是在软件设计阶段考虑的问题,而是解决正在服役的项目的问题。也就是说,当你发现已有的类无法满足新的需求时,才考虑使用适配器模式。
  • 适配器模式实现了对原有接口的扩展,而不是修改原有接口或原有类的代码。这是设计模式的一个重要原则:开闭原则(对扩展开放,对修改封闭)。
  • 适配器模式的使用会增加系统的复杂性和理解难度,因为需要引入额外的适配器类。因此,在使用适配器模式时,需要权衡其带来的好处和增加的复杂性。
  • 适配器模式并不一定能解决所有的接口不兼容问题。在某些情况下,可能需要采用其他的设计模式或者重构代码来解决接口不兼容的问题。

四、适配器与装饰器模式的不同

与装饰器模式(Decorator Pattern)相比,适配器模式和装饰器模式都涉及到对类和接口的包装和扩展,但它们的侧重点和目的不同。


1. 侧重点不同:适配器模式主要解决的是接口不兼容的问题,它并不关注对象的功能增强,而是专注于将已有的功能通过适配器类以新的接口形式暴露给客户端。而装饰器模式则侧重于对对象的功能进行扩展和增强,它通常在不改变原有对象的基础上,动态地给对象添加一些额外的职责或行为。


2. 目的不同:适配器模式的主要目的是解决接口不兼容的问题,使得原本无法协同工作的类能够一起工作。而装饰器模式的主要目的是在不改变原有类的基础上,动态地扩展类的功能,增加类的职责。


3. 包装形式不同:适配器模式通常是通过继承或关联关系来实现接口的适配,它可能会改变原有接口的结构和形式。而装饰器模式则是通过组合关系来扩展对象的功能,它通常保持原有接口的稳定性和一致性。


4. 使用场景不同:适配器模式通常用于系统升级、代码重构等场景,当原有系统的接口无法满足新系统的需求时,可以使用适配器模式进行接口的适配。而装饰器模式则常用于需要在运行时动态地给对象添加功能或职责的场景,如Java IO流中的BufferedInputStream、BufferedReader等就是典型的装饰器模式的应用。


综上所述,适配器模式和装饰器模式虽然都涉及到对类和接口的包装和扩展,但它们的侧重点、目的、包装形式和使用场景都有所不同。在实际应用中,应根据具体的需求和场景来选择合适的设计模式。

相关文章
|
2天前
|
设计模式 Java 开发者
「全网最细 + 实战源码案例」设计模式——适配器模式
适配器模式(Adapter Pattern)是一种结构型设计模式,通过引入适配器类将一个类的接口转换为客户端期望的另一个接口,使原本因接口不兼容而无法协作的类能够协同工作。适配器模式分为类适配器和对象适配器两种,前者通过多重继承实现,后者通过组合方式实现,更常用。该模式适用于遗留系统改造、接口转换和第三方库集成等场景,能提高代码复用性和灵活性,但也可能增加代码复杂性和性能开销。
51 28
|
2月前
|
设计模式 JSON 前端开发
前端必须掌握的设计模式——适配器模式
适配器模式是一种结构型设计模式,用于使接口不兼容的对象能够相互合作。通过在客户端和系统之间引入一个“中间层”适配器,将不同类型的输入数据转换为系统能处理的标准格式,减轻系统的负担,提高扩展性和可维护性。例如,MacBook的扩展坞将多种接口(如HDMI、USB)转换为Type-C接口,实现多接口兼容。
|
3月前
|
设计模式 消息中间件 搜索推荐
Java 设计模式——观察者模式:从优衣库不使用新疆棉事件看系统的动态响应
【11月更文挑战第17天】观察者模式是一种行为设计模式,定义了一对多的依赖关系,使多个观察者对象能直接监听并响应某一主题对象的状态变化。本文介绍了观察者模式的基本概念、商业系统中的应用实例,如优衣库事件中各相关方的动态响应,以及模式的优势和实际系统设计中的应用建议,包括事件驱动架构和消息队列的使用。
|
3月前
|
设计模式 Java 数据库连接
Java编程中的设计模式:单例模式的深度剖析
【10月更文挑战第41天】本文深入探讨了Java中广泛使用的单例设计模式,旨在通过简明扼要的语言和实际示例,帮助读者理解其核心原理和应用。文章将介绍单例模式的重要性、实现方式以及在实际应用中如何优雅地处理多线程问题。
51 4
|
4月前
|
设计模式 Java 程序员
[Java]23种设计模式
本文介绍了设计模式的概念及其七大原则,强调了设计模式在提高代码重用性、可读性、可扩展性和可靠性方面的作用。文章还简要概述了23种设计模式,并提供了进一步学习的资源链接。
85 0
[Java]23种设计模式
|
3月前
|
设计模式 JavaScript Java
Java设计模式:建造者模式详解
建造者模式是一种创建型设计模式,通过将复杂对象的构建过程与表示分离,使得相同的构建过程可以创建不同的表示。本文详细介绍了建造者模式的原理、背景、应用场景及实际Demo,帮助读者更好地理解和应用这一模式。
|
4月前
|
设计模式 监控 算法
Java设计模式梳理:行为型模式(策略,观察者等)
本文详细介绍了Java设计模式中的行为型模式,包括策略模式、观察者模式、责任链模式、模板方法模式和状态模式。通过具体示例代码,深入浅出地讲解了每种模式的应用场景与实现方式。例如,策略模式通过定义一系列算法让客户端在运行时选择所需算法;观察者模式则让多个观察者对象同时监听某一个主题对象,实现松耦合的消息传递机制。此外,还探讨了这些模式与实际开发中的联系,帮助读者更好地理解和应用设计模式,提升代码质量。
Java设计模式梳理:行为型模式(策略,观察者等)
|
5月前
|
存储 设计模式 安全
Java设计模式-备忘录模式(23)
Java设计模式-备忘录模式(23)
|
5月前
|
设计模式 存储 缓存
Java设计模式 - 解释器模式(24)
Java设计模式 - 解释器模式(24)
|
5月前
|
设计模式 安全 Java
Java设计模式-迭代器模式(21)
Java设计模式-迭代器模式(21)