当前位置: 首页 > news >正文

探索设计模式的魅力:深入了解适配器模式-优雅地解决接口不匹配问题


设计模式专栏:http://t.csdnimg.cn/nolNS


目录

一、引言

1. 概述

2. 为什么需要适配器模式

3. 本文的目的和结构

二、简价

1. 适配器模式的定义和特点

  定义

  特点

2. 适配器模式的作用和适用场景

  作用

  适用场景

3. 适配器模式与其他设计模式的比较

三、适配器模式的实现方式

1. 类适配器模式

  结构图

  实现结构

  示例代码

2. 对象适配器模式

  结构图

  实现结构

  示例代码

3. 接口适配器模式

  结构图

  实现结构

  示例代码

四、适配器模式的应用场景

1. 类适配器模式

2. 对象适配器模式

3. 接口适配器模式

五、实战案例

1. 类适配器模式

  实现

  代码示例

2. 对象适配器模式

  实现

  代码示例

3. 接口适配器模式

  实现

  代码示例

六、适配器模式的优缺点和选择

1. 类适配器模式

  优点

  缺点

2. 对象适配器模式

  优点

  缺点

3. 接口适配器模式

  优点

缺点

4.选择哪种选配器模式

七、适配器模式与其他设计模式的结合使用

1. 与装饰器模式结合使用,实现动态适配

2. 与工厂模式结合使用,简化对象创建和适配过程

3. 与观察者模式结合使用,实现事件驱动的适配

4. 与策略模式结合使用,根据不同场景选择不同的适配器

八、总结与展望


一、引言

1. 概述

        适配器模式是一种设计模式,用于将一个类的接口转换成客户端所期望的另一个接口,以解决由于接口不兼容或不匹配而无法协同工作的问题。它使得原本无法一起工作的类能够一起工作,提高了代码的灵活性和复用性,降低了系统间的耦合度。适配器模式主要应用于解决不同组件之间的接口不兼容问题,或者在第三方库与现有系统之间进行集成。

        适配器模式有三种实现方式:类适配器模式对象适配器模式接口适配器模式。类适配器模式通过继承目标类来实现接口转换;对象适配器模式通过包装目标对象来实现接口转换;接口适配器模式通过实现目标接口来实现接口转换。

        使用适配器模式需要注意其优缺点。优点包括提高代码的灵活性和复用性,解决不兼容问题等;缺点包括增加代码的复杂性和学习成本,可能引入额外的性能开销等。因此,在使用适配器模式时,需要根据实际需求选择合适的实现方式,并考虑其适用场景和最佳实践。

        适配器模式可以与其他设计模式结合使用,如与装饰器模式结合实现动态适配,与工厂模式结合简化对象创建和适配过程等。在实际应用中,适配器模式广泛应用于系统集成、遗留代码和新系统之间的桥接、多线程环境下的线程安全适配等方面。

2. 为什么需要适配器模式

        适配器模式是一种经典的设计模式,它的主要作用是解决不同接口之间的兼容性问题。以下是一些需要使用适配器模式的情况:

  1. 接口不兼容: 当系统中的某个接口与另一个接口不兼容时,可以使用适配器模式来进行适配,使得原本无法合作的对象能够协同工作。

  2. 旧系统整合: 在现代化系统中,总是要面对要整合旧系统或者第三方组件的情况,由于接口不兼容,需要适配器模式来进行整合。

  3. 功能复用: 适配器模式还可以用于复用一些功能,例如一个类库中的某个功能非常适合你的项目,但是由于接口不兼容,你可以使用适配器模式来使其能够使用在你的项目中。

  4. 解耦合: 适配器模式可以帮助解决系统之间的耦合度问题,当我们通过适配器模式将两个系统连接在一起时,系统之间的耦合度会降低。

  5. 系统拓展: 在系统开发初期可能考虑不周全,后期需要对现有系统进行功能拓展,适配器模式可以使得拓展系统变得更加容易。

        适配器模式能够帮助我们解决接口不兼容的问题,使得原本无法合作的对象能够协同工作。通过适配器模式,我们可以实现系统间的集成、功能复用、解耦合以及系统拓展,提高系统的灵活性和可维护性。因此,在软件设计中,适配器模式是一种非常重要且常用的设计模式。

3. 本文的目的和结构

  • 介绍适配器模式:适配器模式是一种设计模式,它可以将一个类的接口转换成客户端所期望的另一个接口,从而使原本由于接口不兼容而无法协同工作的类能够一起工作。通过介绍适配器模式的概念、特点和适用场景,可以让读者更好地理解这种设计模式。
  • 分析适配器模式的使用场景:适配器模式适用于需要将两个不兼容的接口进行转换的场景。通过分析实际应用中的案例,可以让读者更好地理解适配器模式的使用场景和优势。
  • 阐述适配器模式的实现方式:适配器模式可以通过不同的方式实现,如类适配器、对象适配器等。通过阐述这些实现方式的原理和优缺点,可以让读者更好地掌握适配器模式的实现技巧。
  • 探讨适配器模式的设计原则:在使用适配器模式时,需要遵循一些设计原则,如组合优于继承、优先使用对象适配等。通过探讨这些原则,可以让读者更好地理解适配器模式的设计思想和应用技巧。
  • 总结适配器模式的优缺点:通过总结适配器模式的优点和缺点,可以让读者更加全面地了解这种设计模式,从而在实际应用中选择合适的场景来使用。

        总之,写这篇适配器模式文章的目的是加深对适配器设计模式的理解,同时也希望对你有一点的帮助,希望我们都能掌握适配器模式的使用场景和实现技巧,以及在设计实践中灵活运用适配器模式来解决问题。

        

二、简价

1. 适配器模式的定义和特点

  定义

        将一个类的接又转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

  特点

  1. 封装性: 适配器模式通过封装被适配者的实现细节,隐藏了具体的实现方式,使得客户端与被适配者解耦,降低了系统的复杂性。

  2. 灵活性: 适配器模式可以在不修改现有代码的情况下增加、替换或者重用已有的适配器,使得系统具有更好的可扩展性和可维护性。

  3. 透明性: 适配器模式对客户端是透明的,客户端无需关心具体的适配器实现细节,只需通过目标接口与适配器进行交互。

  4. 单一职责原则: 适配器模式让不兼容的接口在一个单一的适配器中进行适配和转换,每个适配器只负责转换一个特定的接口,符合单一职责原则。

  5. 开闭原则: 适配器模式符合开闭原则,因为在新增适配器时,无需修改现有的客户端代码,只需要添加新的适配器即可。

  6. 性能考量: 适配器模式可在一定程度上引入性能损耗,因为需要进行接口的转换和适配操作。但通常情况下,适配器模式的性能影响是可以接受的,特别是在实现中可以采用缓存等优化措施。

        适配器模式是一种通过适配器来解决接口不兼容问题的设计模式。它具有兼容性、封装性、灵活性、透明性、单一职责原则、开闭原则和性能考量等特点。通过合理应用适配器模式,可以提高系统的灵活性、可维护性和可扩展性。

2. 适配器模式的作用和适用场景

  作用

  1. 解决接口不兼容问题: 当系统中的两个接口不兼容时,适配器模式可以帮助我们在两个不同的接口之间建立联系,使得原本无法合作的对象能够协同工作。

  2. 实现接口转换和适配: 适配器模式可以通过适配器将一个类的接口转换为客户端所期望的接口,从而实现对不兼容接口的适配。

  3. 提供接口的灵活性和可扩展性: 使用适配器模式,可以将适配器作为一个中间层,使系统的组件之间的耦合度降低。当需要引入新的组件时,只需增加一个适配器,而无需修改现有的组件代码。

  4. 功能复用: 适配器模式可以帮助我们复用一些原本不兼容的功能。通过将这些功能封装在适配器中,使其能够在其他系统中使用。

  5. 系统整合: 在现代化系统中,我们常常需要整合旧系统或第三方组件。由于接口不兼容,适配器模式可以帮助我们将不兼容的接口整合在一起。

        适配器模式的作用是通过适配器将不兼容的接口进行适配和转换,使得系统中的不同组件能够协同工作。它提供了灵活性、可扩展性和功能复用的特性,使得系统的设计更加合理和可维护。通过合理应用适配器模式,可以避免修改现有代码,同时实现系统的集成、功能复用和扩展性提升。

  适用场景

  1. 集成旧系统: 当需要集成一个已有的系统或组件,但其接口与现有系统不兼容时,适配器模式可以使用,以便两者能够协同工作。

  2. 整合第三方库: 在使用第三方库或服务时,由于接口不兼容而无法直接对接时,可以使用适配器模式进行适配,使其能够与现有系统协同工作。

  3. 功能复用: 当需要重用已有,但与当前系统不兼容的功能时,适配器模式可以帮助我们将这些功能适配到系统中。

  4. 系统拓展: 当系统功能需要拓展,同时需要与已有系统或外部组件进行交互时,适配器模式可以用来构建新功能与旧功能的桥梁。

  5. 跨平台开发: 在跨平台开发中,不同平台之间可能存在接口不兼容的情况,适配器模式可以帮助我们在不同平台之间实现统一的接口。

  6. 遗留代码修改: 当需要与遗留系统进行交互,但由于接口不兼容而无法直接整合时,适配器模式可以帮助我们与遗留系统进行对接。

  7. 外部数据格式转换: 当需要将外部数据格式转换为本地系统所需的数据格式时,适配器模式可以用来进行数据格式的转换与适配。

        适配器模式适用于需要解决不兼容接口的场景,同时适用于需要整合、扩展、集成或重用功能的情况。通过合理应用适配器模式,可以使系统变得更具灵活性和可扩展性,同时降低系统组件之间的耦合度,提高系统的可维护性和可复用性。

3. 适配器模式与其他设计模式的比较

  1. 适配器模式 vs 装饰器模式: 适配器模式和装饰器模式都可以用于在现有对象上增加新的功能,但它们的目的和使用场景略有不同。适配器模式主要用于解决接口不兼容的问题,通过适配器将不同接口转换为可兼容的接口。而装饰器模式用于动态地为一个对象添加额外的行为,而且不改变其原有接口。所以适配器模式的关注点是接口转换,而装饰器模式的关注点是动态扩展。

  2. 适配器模式 vs 桥接模式: 适配器模式和桥接模式都可以用于解决不同接口之间的兼容性问题,但它们的实现方式和应用场景有所不同。适配器模式将一个接口转换成客户端所期望的接口,以使得原本不兼容的对象能够协同工作。而桥接模式主要用于将抽象部分与其实现部分解耦,使它们可以独立地变化。适配器模式更注重接口转换和兼容性,而桥接模式更注重抽象和实现的分离。

  3. 适配器模式 vs 外观模式: 适配器模式和外观模式都可以用于简化复杂系统的访问,并提供简单的接口给客户端使用。但它们的主要区别在于关注点的不同。适配器模式主要用于解决不兼容接口的问题,通过适配器将一个接口转换为另一个兼容的接口。而外观模式主要用于为复杂系统提供一个简单的接口,集中封装系统的复杂性,使得使用者能够更方便地与系统交互。

        适配器模式与其他设计模式相比,它的主要作用是解决接口不兼容的问题,同时提供接口转换和适配功能。它与装饰器模式、桥接模式和外观模式等其他设计模式在目的、实现方式和应用场景上有所区别。根据具体的需求和设计情况,我们可以选择合适的设计模式来解决问题。

        

三、适配器模式的实现方式

1. 类适配器模式

        类适配器模式是适配器模式的一种实现方式,它通过继承来实现适配器。在类适配器模式中,适配器类继承了适配者类,并实现了目标接口,从而使得适配器类具备了适配者类的功能,并且可以被客户端使用。

  结构图

  实现结构

  1. 目标接口(Target):定义客户所期待的接口,可以是抽象类或接口。适配器通过实现这个接口来完成适配。

  2. 被适配类(Adaptee):需要被适配的类或接口,它定义了客户不需要的接口。

  3. 适配器(Adapter):适配器类继承了被适配类,并实现了目标接口。在适配器类中,通过调用被适配类的方法来实现目标接口中定义的方法。

  示例代码

// 目标接口
interface Target {void request();
}// 被适配类
class Adaptee {void specificRequest() {System.out.println("Adaptee's specific request");}
}// 适配器类
class Adapter extends Adaptee implements Target {@Overridepublic void request() {specificRequest();}
}// 客户端代码
public class Client {public static void main(String[] args) {Target target = new Adapter();  // 使用适配器target.request();}
}

        在上面的示例中,Target 是目标接口,Adaptee 是被适配类,Adapter 是适配器类。适配器类 Adapter 继承了被适配类 Adaptee,并实现了目标接口 Target。在适配器类中,通过调用被适配类的方法 specificRequest() 来实现目标接口中定义的方法 request()。最后,在客户端代码中,通过创建适配器对象,并调用目标接口的方法来实现适配功能。

        这就是类适配器模式的基本实现结构,通过继承被适配类和实现目标接口,适配器类能够实现目标接口,并将客户端的请求适配到被适配类的方法上。

2. 对象适配器模式

        对象适配器模式是适配器模式的另一种实现方式,它通过组合关系来实现适配器。在对象适配器模式中,适配器类持有一个适配者类的实例,并实现了目标接口,从而使得适配器类具备了适配者类的功能,并且可以被客户端使用。

  结构图

  实现结构

  1. 目标接口(Target):客户端所期待的接口。
  2. 适配者类(Adaptee):需要被适配的类,即现有系统中已经存在的类。
  3. 适配器类(Adapter):持有适配者类的实例,并实现了目标接口,用于将适配者类的接口转换成客户端所期待的接口。

  示例代码

// 目标接口
interface Target {void request();
}// 被适配类
class Adaptee {void specificRequest() {System.out.println("Adaptee's specific request");}
}// 适配器类
class Adapter implements Target {private Adaptee adaptee;Adapter(Adaptee adaptee) {this.adaptee = adaptee;}@Overridepublic void request() {adaptee.specificRequest();}
}// 客户端代码
public class Client {public static void main(String[] args) {Adaptee adaptee = new Adaptee();Target target = new Adapter(adaptee);  // 使用适配器,传入被适配类的实例target.request();}
}

        在上面的示例中,Target 是目标接口,Adaptee 是被适配类,Adapter 是适配器类。适配器类 Adapter 持有被适配类 Adaptee 的实例,并实现了目标接口 Target。在适配器类中,通过调用被适配类实例的方法 specificRequest() 来实现目标接口中定义的方法 request()。最后,在客户端代码中,先创建被适配类的实例,并将其传递给适配器类的构造方法,然后通过适配器对象来调用目标接口的方法来实现适配功能。

        这就是对象适配器模式的基本实现结构,通过持有被适配类的实例,并实现目标接口,适配器类能够实现目标接口,并将客户端的请求适配到被适配类的方法上。

3. 接口适配器模式

        接口适配器模式是适配器模式的一种变体,也被称为缺省适配器模式。它主要用于解决一个接口中定义过多的方法,而不希望实现全部方法的情况。

        在接口适配器模式中,适配器类实现了目标接口,并提供了一个空的默认实现,然后具体的适配器类继承适配器类,只需要重写感兴趣的方法即可。

  结构图

  实现结构

  1. 目标接口(Target):客户端所期待的接口。可以是一个接口或抽象类。
  2. 适配器类(Adapter):实现了目标接口,并提供了一个空的默认实现。该适配器类可以是抽象类或具体类。
  3. 具体适配器类(ConcreteAdapter):继承适配器类,并重写感兴趣的方法,以实现适配的功能。

  示例代码

// 目标接口
interface Target {void method1();void method2();void method3();
}// 适配器类(提供默认实现)
abstract class Adapter implements Target {public void method1() {}public void method2() {}public void method3() {}
}// 具体适配器类(只重写感兴趣的方法)
class ConcreteAdapter extends Adapter {public void method1() {System.out.println("Method1 of ConcreteAdapter");}
}// 客户端代码
public class Client {public static void main(String[] args) {Target target = new ConcreteAdapter(); // 使用具体适配器类target.method1(); // 调用适配器的方法target.method2(); // 使用适配器提供的默认实现target.method3(); // 使用适配器提供的默认实现}
}

        在这个示例中,由于目标接口定义了多个方法,但客户端只关心其中的一个方法,所以我们通过接口适配器模式来进行适配。Adapter 类提供了目标接口的默认实现,而 ConcreteAdapter 类继承 Adapter 类并重写了感兴趣的方法,从而实现适配。

        这就是接口适配器模式的实现方式,通过提供默认实现和具体适配器的方式来适配目标接口。这种方式可以灵活地选择需要重写的方法,避免了实现全部方法的繁琐。

        

四、适配器模式的应用场景

1. 类适配器模式

  1. 需要将一个类适配到另一个类接口的情况。
  2. 适配者类的方法和目标接口的方法之间具有相似的功能。
  3. 不需要适配者类的子类进行适配。

2. 对象适配器模式

  1. 需要将一个对象适配到另一个类接口的情况。
  2. 适配者类的方法和目标接口的方法之间具有相似的功能。
  3. 需要动态地改变适配者对象。

3. 接口适配器模式

  1. 需要利用已有的接口,并且只想实现其中的一部分方法。
  2. 需要为多个类提供不同的适配接口。
  3. 希望增加一个统一的接口来方便客户端调用。

        

五、实战案例

1. 类适配器模式

  实现

        一个典型的类适配器模式的实战案例是手机充电器的适配器。以德国的欧标充电器和中国的插头插座为例,在德国的欧标充电器无法直接插入中国的插头插座,但是可以通过适配器进行转接。

        在这个例子中,可以采用类适配器模式来实现适配器,具体实现如下:

  • 目标接口(Target):中国的插头插座接口
  • 适配者类(Adaptee):德国的欧标充电器
  • 适配器类(Adapter):继承自Adaptee并实现了Target接口,用于将欧标充电器的接口转换成中国插头插座的接口

  代码示例

// 目标接口
interface ChineseSocket {void chargeWithChineseSocket();
}// 适配者类
class GermanSocket {public void chargeWithGermanSocket() {System.out.println("Charging with German socket");}
}// 适配器类
class SocketAdapter extends GermanSocket implements ChineseSocket {public void chargeWithChineseSocket() {chargeWithGermanSocket(); // 使用德国插头充电}
}// 客户端代码
public class Client {public static void main(String[] args) {ChineseSocket chineseSocket = new SocketAdapter(); // 使用适配器chineseSocket.chargeWithChineseSocket(); // 调用适配器的方法}
}

        在这个案例中,德国的欧标充电器(Adaptee)无法直接插入中国的插头插座(Target),但是通过类适配器模式中的SocketAdapter,德国的欧标充电器的接口被转换成了可以插入中国插头插座的接口,从而实现了适配。

        这个手机充电器的适配器案例典型地展示了类适配器模式的实战应用,通过继承适配者类并实现目标接口,实现了充电器的适配功能,使得德国的欧标充电器可以充电在中国的插头插座上。

2. 对象适配器模式

  实现

        一个典型的对象适配器模式的实战案例是音频播放器的适配器。假设我们有一个基于Windows系统的音频播放器类,其中定义了playAudio()方法用于播放音频文件。现在需要将这个音频播放器适配到基于Mac系统的应用中,同时又不改变原有的音频播放器类。

        在这个例子中,可以使用对象适配器模式来实现适配器,具体实现如下:

  • 目标接口(Target):Mac系统的音频播放器接口
  • 适配者类(Adaptee):Windows系统的音频播放器类
  • 适配器类(Adapter):持有适配者类的实例,并实现了目标接口,用于将Windows音频播放器的方法转换成Mac音频播放器的方法

  代码示例

// 目标接口
interface MacAudioPlayer {void playMacAudio();
}// 适配者类
class WindowsAudioPlayer {public void playAudio() {System.out.println("Playing audio with Windows audio player");}
}// 适配器类
class AudioPlayerAdapter implements MacAudioPlayer {private WindowsAudioPlayer windowsPlayer; // 持有适配者类的实例public AudioPlayerAdapter(WindowsAudioPlayer windowsPlayer) {this.windowsPlayer = windowsPlayer;}public void playMacAudio() {windowsPlayer.playAudio(); // 调用适配者类的方法来实现适配}
}// 客户端代码
public class Client {public static void main(String[] args) {WindowsAudioPlayer windowsPlayer = new WindowsAudioPlayer();MacAudioPlayer macPlayer = new AudioPlayerAdapter(windowsPlayer); // 使用适配器macPlayer.playMacAudio(); // 调用适配器的方法}
}

        在这个案例中,WindowsAudioPlayer 是需要被适配的类,AudioPlayerAdapter 持有了 WindowsAudioPlayer 的实例,并实现了 MacAudioPlayer 接口,从而使得 AudioPlayerAdapter 成为了 MacAudioPlayer 接口的一个具体实现。客户端代码可以通过 MacAudioPlayer 接口来访问适配器的功能,而适配器内部调用了适配者类的方法来实现适配。

        这个音频播放器的适配器案例展示了对象适配器模式的实战应用,通过持有适配者类的实例并实现目标接口,实现了适配器的功能,使得Windows系统的音频播放器可以适配到Mac系统的应用中。

3. 接口适配器模式

  实现

        一个典型的接口适配器模式的实战案例是日历提醒应用的适配器。假设我们有一个日历提醒应用,它可以通过多种方式进行提醒,包括短信、邮件和推送通知等。现在需要将这个日历提醒应用适配到一个新的第三方消息服务提供商,该提供商仅支持通过邮件进行提醒。

        在这个例子中,可以使用接口适配器模式来实现适配器,具体实现如下:

  • 目标接口(Target):第三方消息服务提供商的邮件提醒接口
  • 适配器类(Adapter):实现了目标接口,并提供了适配的功能
  • 具体适配器类(ConcreteAdapter):继承适配器类,并重写感兴趣的方法,以实现适配 

  代码示例

// 目标接口
interface ThirdPartyEmailReminder {void sendEmailReminder();
}// 适配器类(提供适配的功能)
class CalendarReminderAdapter implements ThirdPartyEmailReminder {private CalendarReminder calendarReminder;  // 日历提醒应用的实例public CalendarReminderAdapter(CalendarReminder calendarReminder) {this.calendarReminder = calendarReminder;}public void sendEmailReminder() {// 调用日历提醒应用的邮件提醒方法来实现适配calendarReminder.sendEmailReminder();}
}// 具体适配器类(可选,根据需要选择实现感兴趣的方法)
class CustomCalendarReminderAdapter extends CalendarReminderAdapter {public CustomCalendarReminderAdapter(CalendarReminder calendarReminder) {super(calendarReminder);}// 根据需要重写感兴趣的方法public void sendEmailReminder() {// 添加自定义的适配逻辑System.out.println("Sending email reminder through custom adapter");super.sendEmailReminder();}
}// 日历提醒应用类
class CalendarReminder {public void sendEmailReminder() {System.out.println("Sending email reminder through calendar reminder app");}
}// 客户端代码
public class Client {public static void main(String[] args) {CalendarReminder calendarReminder = new CalendarReminder();ThirdPartyEmailReminder adapter = new CalendarReminderAdapter(calendarReminder); // 使用适配器adapter.sendEmailReminder(); // 调用适配器的方法ThirdPartyEmailReminder customAdapter = new CustomCalendarReminderAdapter(calendarReminder); // 使用具体适配器customAdapter.sendEmailReminder(); // 调用具体适配器的方法}
}

        在这个案例中,日历提醒应用(CalendarReminder)是需要被适配的类,CalendarReminderAdapter 实现了 ThirdPartyEmailReminder 接口并提供了适配的功能,在适配器中将调用日历提醒应用的邮件提醒方法来实现适配。

        这个日历提醒应用的适配器案例展示了接口适配器模式的实战应用,通过实现目标接口并提供适配的功能来实现适配器,从而使得日历提醒应用可以适配到第三方消息服务提供商的邮件提醒接口中。

六、适配器模式的优缺点和选择

1. 类适配器模式

  优点

  1. 结构简单:类适配器模式只需定义一个适配器类,通过继承和实现目标接口的方式很容易对适配者进行适配,结构相对简单。
  2. 单一职责:适配器通过继承适配者类和实现目标接口的方式,将适配的逻辑与适配者类逻辑分离,符合单一职责原则。

  缺点

  1. 无法适配适配者子类:如果适配者类有子类,那么在类适配器模式中无法对适配者及其子类都进行适配,因为适配器类已经继承了适配者类,导致无法适配适配者类的子类。
  2. 多重继承问题:在一些编程语言中,由于类适配器模式需要同时继承适配者类和实现目标接口,因此会出现多重继承的问题,而某些编程语言不支持多重继承。

2. 对象适配器模式

  优点

  1. 灵活性高:对象适配器模式使用组合的方式来引入适配者对象,因此在运行时可以动态地更换适配者对象,实现了更高的灵活性。
  2. 降低耦合: 适配器和适配者类可以相对独立地变化,降低了适配器与适配者之间的耦合度。

  缺点

  1. 无法适配被final修饰的类:如果适配者类被final关键字修饰,那么无法使用对象适配器模式对其进行适配,因为无法继承该类。
  2. 需要额外引入对象:对象适配器模式需要引入适配者对象,可能会导致额外的内存开销,尤其是在大规模使用时。

3. 接口适配器模式

  优点

  1. 灵活性高:接口适配器模式可以根据需要选择性地实现目标接口中的方法,避免了对所有方法的空实现。
  2. 解耦:适配器和被适配者之间通过接口进行通信,使得它们之间的关系更加松散,降低了耦合性。 

缺点

  1. 代码可读性较差:接口适配器模式的实现通常需要定义一个抽象适配器类并提供接口方法的空实现,这可能会导致代码的可读性较差,增加了代码的复杂性。
  2. 过多的实现类:如果目标接口中定义了很多方法,而适配器只需要实现其中的少数方法,那么需要为每个方法都提供一个空实现,可能会导致产生大量的适配器子类,增加了代码的维护成本。

4.选择哪种选配器模式

        选择适配器模式的具体实现方式(类适配器模式、对象适配器模式和接口适配器模式)取决于以下几个因素:

1. 继承关系:如果适配器需要适配的类已经有一个父类,并且适配器需要继承这个父类的行为,那么可以选择类适配器模式。

  • 类适配器模式使用继承来适配目标类和适配者类,因此只适用于适配器类可以同时继承目标类和适配者类的情况。

2. 对象组合:如果适配器需要适配的类是一个接口,或者适配器需要同时适配多个类,或者适配器希望将适配者类对象作为一个独立的成员变量,那么可以选择对象适配器模式。

  • 对象适配器模式使用对象组合来适配目标类和适配者类,因此适用于适配器类需要适配多个类或者实现接口的情况。

3. 接口实现:如果适配器只需要适配某个接口的部分方法,或者希望为适配的接口提供默认实现,那么可以选择接口适配器模式。

  • 接口适配器模式使用抽象类来实现适配器,因此适用于适配器类只需要实现部分方法或者提供默认实现的情况。

        需要注意的是,选择适配器模式的具体实现方式要根据实际需求和情况来确定。在选择的过程中,需要考虑目标类、适配者类以及适配器类之间的关系,以及需要适配的行为等因素。

        

七、适配器模式与其他设计模式的结合使用

1. 与装饰器模式结合使用,实现动态适配

        适配器模式和装饰器模式是两种设计模式,它们可以结合使用来实现动态适配的功能。

适配器模式用于将一个类的接口转换成客户期望的另一个接口,使得原本由于接口不兼容而无法合作的类能够一起工作。而装饰器模式用于在不改变原有对象接口的情况下,动态地为对象添加额外的行为。

        当需要动态适配的功能时,可以使用适配器模式来适配不同的接口,并且通过装饰器模式在适配后的对象上添加额外的行为。具体步骤可以如下:

  1. 创建适配器类,实现目标接口,并引入适配者类。
  2. 创建装饰器类,实现目标接口,并包含一个适配器对象作为成员变量。
  3. 在装饰器类的方法中,先调用适配器对象的对应方法进行适配操作,然后再进行额外的行为添加。

  示例代码

// 定义目标接口
interface Target {void request();
}// 定义适配者类
class Adaptee {public void specificRequest() {System.out.println("Adaptee's specific request");}
}// 定义适配器类
class Adapter implements Target {private Adaptee adaptee;public Adapter(Adaptee adaptee) {this.adaptee = adaptee;}public void request() {adaptee.specificRequest();}
}// 定义装饰器类
class Decorator implements Target {private Target target;public Decorator(Target target) {this.target = target;}public void request() {// 在调用适配器方法之前可以添加额外的行为System.out.println("Decorator adds extra behavior before calling the request method");target.request();// 在调用适配器方法之后可以添加额外的行为System.out.println("Decorator adds extra behavior after calling the request method");}
}// 测试代码
public class Main {public static void main(String[] args) {// 实例化适配者对象Adaptee adaptee = new Adaptee();// 实例化适配器对象,并传入适配者对象Adapter adapter = new Adapter(adaptee);// 实例化装饰器对象,并传入适配器对象Decorator decorator = new Decorator(adapter);// 调用装饰器对象的方法,实现动态适配和添加额外行为decorator.request();}
}

        在这个示例中,Adaptee 类具有一个 specificRequest 方法,而 Target 接口具有一个 request 方法。通过 Adapter 类,将 Adaptee 的 specificRequest 方法适配到 Target 的 request 方法中。然后通过 Decorator 类,可以在调用适配器方法之前和之后添加额外的行为。

        运行这段代码,输出结果将会是:

Decorator adds extra behavior before calling the request method
Adaptee's specific request
Decorator adds extra behavior after calling the request method

        这个例子展示了如何在 Java 中结合适配器模式和装饰器模式来实现动态适配的功能。

2. 与工厂模式结合使用,简化对象创建和适配过程

在适配器模式与工厂模式结合使用时,可以按照以下具体步骤进行实现:

  1. 定义目标接口(Target):目标接口是适配器对象需要实现的接口。它规定了适配器对象要提供的方法。

  2. 定义适配者类(Adaptee):适配者类是已经存在的一个具体类,其中包含了需要被适配的方法。

  3. 定义适配器类(Adapter):适配器类实现了目标接口,并且内部持有一个适配者对象的引用。适配器类将适配者类的方法适配到目标接口的方法中。

  4. 定义工厂接口(Factory):工厂接口是用于创建适配器对象的接口,声明了创建目标对象的方法。

  5. 实现具体的工厂类(具体工厂):具体的工厂类实现了工厂接口,负责创建适配器对象。在工厂类中实例化适配者对象,并将其作为参数传给适配器对象。

  6. 在客户端中使用工厂类创建目标对象并调用方法:在客户端中,通过具体的工厂类创建适配器对象,然后调用其方法。

  示例代码:

// 定义目标接口
interface Target {void request();
}// 定义适配者类
class Adaptee {public void specificRequest() {System.out.println("Adaptee's specific request");}
}// 定义适配器类
class Adapter implements Target {private Adaptee adaptee;public Adapter(Adaptee adaptee) {this.adaptee = adaptee;}public void request() {adaptee.specificRequest();}
}// 定义工厂接口
interface TargetFactory {Target createTarget();
}// 实现具体的工厂类
class AdapterFactory implements TargetFactory {public Target createTarget() {Adaptee adaptee = new Adaptee();return new Adapter(adaptee);}
}// 测试代码
public class Main {public static void main(String[] args) {// 使用工厂类创建目标对象TargetFactory factory = new AdapterFactory();Target target = factory.createTarget();// 调用目标对象的方法target.request();}
}

        通过以上步骤,我们定义了目标接口、适配者类、适配器类、工厂接口和具体的工厂类,并在客户端中使用工厂类来创建目标对象并调用其方法。从而实现了适配器模式与工厂模式的结合使用。  

3. 与观察者模式结合使用,实现事件驱动的适配

        适配器模式与观察者模式可以结合使用,用于将已有的对象适配为观察者对象。下面是适配器模式与观察者模式结合使用的实现步骤

  1. 定义目标接口(Subject):目标接口是观察者模式中被观察的对象,包含了添加、删除和通知观察者的方法。

  2. 定义适配者类(Adaptee):适配者类是已有的一个具体类,它包含了一些可观察的状态,但其方法和观察者接口不兼容。

  3. 定义适配器类(Adapter):适配器类实现了目标接口,并在内部持有一个适配者对象的引用。适配器类将适配者类的可观察状态通知转化为目标接口中通知观察者的方法调用。

  4. 定义观察者接口(Observer):观察者接口是观察者模式中的观察者对象,包含了接收到通知后的处理方法。

  5. 实现具体的观察者类(具体观察者):具体的观察者类实现了观察者接口,并定义了接收到通知后的处理逻辑。

  6. 在适配器类中维护观察者列表:在适配器类中维护一个观察者列表,用于管理注册的观察者对象。

  7. 在适配器类的方法中转发适配者的通知:适配器类的方法中,将适配者的可观察状态变化通知转发给观察者列表中的每个观察者对象。

  示例代码

import java.util.ArrayList;
import java.util.List;// 定义目标接口
interface Subject {void registerObserver(Observer observer);void removeObserver(Observer observer);void notifyObservers();
}// 定义适配者类
class Adaptee {private boolean observableState;public void setObservableState(boolean state) {observableState = state;}public boolean getObservableState() {return observableState;}
}// 定义适配器类
class Adapter implements Subject {private Adaptee adaptee;private List<Observer> observers;public Adapter(Adaptee adaptee) {this.adaptee = adaptee;this.observers = new ArrayList<>();}public void registerObserver(Observer observer) {observers.add(observer);}public void removeObserver(Observer observer) {observers.remove(observer);}public void notifyObservers() {boolean state = adaptee.getObservableState();for (Observer observer : observers) {observer.update(state);}}
}// 定义观察者接口
interface Observer {void update(boolean state);
}// 实现具体的观察者类
class ConcreteObserver implements Observer {public void update(boolean state) {System.out.println("Received notification: " + state);}
}// 测试代码
public class Main {public static void main(String[] args) {// 创建适配者对象Adaptee adaptee = new Adaptee();// 创建适配器对象Adapter adapter = new Adapter(adaptee);// 创建观察者对象Observer observer = new ConcreteObserver();// 注册观察者adapter.registerObserver(observer);// 设置适配者对象的可观察状态adaptee.setObservableState(true);// 通知观察者adapter.notifyObservers();}
}

        通过以上步骤,我们定义了目标接口、适配者类、适配器类、观察者接口以及具体的观察者类,并在适配器类中维护了观察者列表。在客户端中,通过创建适配者对象和适配器对象,并注册观察者、设置可观察状态以及调用通知方法,实现适配器模式与观察者模式的结合使用。

4. 与策略模式结合使用,根据不同场景选择不同的适配器

        适配器模式与策略模式结合使用可以通过策略模式选择不同的适配器来实现根据不同场景选择不同的适配器的功能。下面是适配器模式与策略模式结合使用的实现步骤及Java实现示例:

  1. 定义目标接口(Target):目标接口是适配器对象需要实现的接口。

  2. 定义适配者类(Adaptee):适配者类是已经存在的一个具体类,它的方法和目标接口的方法不兼容。

  3. 定义适配器接口(Adapter):适配器接口也是一个接口,它定义了适配器对象的通用方法。

  4. 定义适配器策略接口(AdapterStrategy):适配器策略接口是一个策略模式的接口,它定义了选择适配器的策略方法。

  5. 实现具体的适配器策略类(ConcreteAdapterStrategy):具体的适配器策略类实现了适配器策略接口,并在策略方法中根据场景选择具体的适配器对象。

  6. 在适配器类中实现目标接口和适配器接口:在适配器类中实现目标接口的方法,并在适配器接口的方法中调用具体适配器的方法。

  7. 根据不同的场景选择适配器策略:在具体的适配器策略类中,根据不同的场景选择具体的适配器对象。

  示例代码

// 定义目标接口
interface Target {void request();
}// 定义适配者类
class Adaptee {public void specificRequest() {System.out.println("Adaptee's specific request");}
}// 定义适配器接口
interface Adapter {void specificRequest();
}// 定义适配器策略接口
interface AdapterStrategy {Adapter getAdapter();
}// 定义具体的适配器策略类
class ConcreteAdapterStrategy implements AdapterStrategy {private String scenario;public ConcreteAdapterStrategy(String scenario) {this.scenario = scenario;}public Adapter getAdapter() {Adapter adapter;if (scenario.equals("A")) {adapter = new Adapter() {private Adaptee adaptee = new Adaptee();public void specificRequest() {adaptee.specificRequest();}};} else if (scenario.equals("B")) {adapter = new Adapter() {public void specificRequest() {System.out.println("Custom specific request");}};} else {adapter = null;}return adapter;}
}// 测试代码
public class Main {public static void main(String[] args) {String scenario = "A"; // 可以根据不同的场景选择适配器策略AdapterStrategy strategy = new ConcreteAdapterStrategy(scenario);Adapter adapter = strategy.getAdapter();if (adapter != null) {adapter.specificRequest();}}
}

        

八、总结与展望

  本文的总结

        本文对适配器模式进行了全面深入的探讨,包括其定义、特点、适用场景、实现方式、应用场景、优缺点以及与其他设计模式的结合使用。文章首先介绍了适配器模式的基本概念和重要性,然后详细分析了类适配器模式、对象适配器模式和接口适配器模式的实现方式和特点。接着,通过实战案例进一步阐述了适配器模式在不同场景下的应用。最后,文章总结了适配器模式的优缺点,并探讨了其与其他设计模式的结合使用,从而更好地理解和应用适配器模式。

  对未来研究的建议和展望

随着软件系统的复杂性和多样性不断增加,适配器模式在未来仍将发挥重要作用。针对适配器模式的应用,以下是对未来研究的建议和展望:

  1. 动态适配技术研究:进一步研究如何在运行时动态地适配接口,以满足不断变化的需求。这可能涉及到反射、代理等技术的研究和应用。
  2. 适配器模式与其他设计模式的结合使用:进一步探索适配器模式与其它设计模式(如装饰器模式、工厂模式、观察者模式等)的结合方式,以提高软件系统的灵活性和可扩展性。
  3. 适配器模式在不同领域的应用研究:研究适配器模式在非传统领域(如物联网、人工智能等)的应用,探索其在解决实际问题中的潜力。
  4. 性能与可维护性研究:进一步研究适配器模式在提高软件性能和可维护性方面的作用,以及如何通过优化适配器模式来降低软件开发的成本。
  5. 理论体系研究:深入探讨适配器模式的理论基础,完善其设计原则和方法论,为适配器模式的进一步应用提供指导。
  6. 案例与实践研究:通过更多的实际案例和实践经验,深入挖掘适配器模式的适用场景和最佳实践,促进其在软件开发中的广泛应用。
  7. 教育和培训研究:开展针对适配器模式的教育和培训工作,提高开发人员对适配器模式的认识和应用能力,推动其在软件开发行业的普及和应用。

相关文章:

探索设计模式的魅力:深入了解适配器模式-优雅地解决接口不匹配问题

设计模式专栏&#xff1a;http://t.csdnimg.cn/nolNS 目录 一、引言 1. 概述 2. 为什么需要适配器模式 3. 本文的目的和结构 二、简价 1. 适配器模式的定义和特点 定义 特点 2. 适配器模式的作用和适用场景 作用 适用场景 3. 适配器模式与其他设计模式的比较 三、适配…...

matlab窗函数-hann窗和hamming窗函数

窗函数的作用 在时域上&#xff0c;窗函数可以看作是对原始信号进行截断或调制的加权函数。这些窗函数通常在时域上是有限的宽度&#xff0c;并且具有对称性&#xff0c;如矩形窗、汉宁窗、汉明窗和布莱克曼窗等。例如&#xff0c;汉明窗是一种对称窗函数&#xff0c;它可以用…...

Java项目实战--瑞吉外卖DAY03

目录 P22新增员工_编写全局异常处理器 P23新增员工_完善全局异常处理器并测试 p24新增员工_小结 P27员工分页查询_代码开发1 P28员工分页查询_代码开发2 P22新增员工_编写全局异常处理器 在COMMON新增全局异常捕获的类&#xff0c;其实就是代理我们这些controlle。通过aop把…...

docker 里使用vcs 2018 verdi等eda 图形界面

书接上文。之前借用别人的docker&#xff0c;使用EDA工具&#xff0c;苦于没有图形界面。如果只是编码&#xff0c;编译可能问题不大&#xff0c;但是如果要看波形之类的&#xff0c;就没法实现了。 docker 使用 vcs/2018 Verdi等 eda 软件-CSDN博客https://blog.csdn.net/guy…...

OpenHarmony—不支持解构赋值

规则&#xff1a;arkts-no-destruct-assignment 级别&#xff1a;错误 ArkTS不支持解构赋值。可使用其他替代方法&#xff0c;例如&#xff0c;使用临时变量。 TypeScript let [one, two] [1, 2]; // 此处需要分号 [one, two] [two, one];let head, tail [head, ...tail]…...

让AI帮你说话--GPT-SoVITS教程

有时候我们在录制视频的时候&#xff0c;由于周边环境嘈杂或者录音设备问题需要后期配音&#xff0c;这样就比较麻烦。一个比较直观的想法就是能不能将写好的视频脚本直接转换成我们的声音&#xff0c;让AI帮我们完成配音呢&#xff1f;在语音合成领域已经有很多这类工作了&…...

线性回归需要满足的几个假设

线性回归模型是基于一些假设构建的&#xff0c;这些假设有助于确保模型的有效性和可解释性。以下是线性回归需要满足的几个主要假设&#xff1a; 线性关系假设&#xff08;Linearity&#xff09;: 线性回归假设因变量&#xff08;目标变量&#xff09;与自变量&#xff08;特征…...

go语言(十八)---- goroutine

一、goroutine package mainimport ("fmt""time" )func main() {//用go创建承载一个形参为空&#xff0c;返回值为空的一个函数go func() {defer fmt.Println("A.defer")func() {defer fmt.Println("B.defer")//退出当前goroutinefmt…...

城市开发区视频系统建设方案:打造视频基座、加强图像数据治理

一、背景需求 随着城市建设的步伐日益加快&#xff0c;开发区已经成为了我国工业化、城镇化和对外开放的重要载体。自贸区、开发区和产业园的管理工作自然也变得至关重要。在城市经开区的展览展示馆、进出口商品展示交易中心等地&#xff0c;数千路监控摄像头遍布各角落&#…...

宏景eHRSmsAcceptGSTXServle存在XXE漏洞

指纹特征 app"HJSOFT-HCM"漏洞复现 POST /servlet/sms/SmsAcceptGSTXServlet HTTP/1.1 Host: User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36 Content-Length: 137 Content…...

LLVM实战之模块化设计

目录 1. llvm基础理念 2. 准备工作 3. 详细步骤 3.1 指令合并优化 3.2 无用参数消除优化 4. Pass管理器(Pass Manager)...

可以运行在浏览器的Windows 2000

Windows 2000 可以在浏览器里跑了&#xff0c;缺点就是速度慢。 JSLinux JSLinux 在浏览器中运行 Linux 或其他操作系统&#xff01; 可以使用以下仿真系统&#xff1a; 中央处理器操作系统用户 界面VF同步 访问启动 链接TEMU 配置评论x86阿尔派Linux 3.12.0安慰是的点击这…...

CUDA笔记

CUDA笔记 nvidia-smi 命令使用 nvidiasmi -q&#xff1a;查询GPU详细信息&#xff1b; nvidia-smi -q -l 0&#xff1a;查询特定GPU详细信息&#xff1b; nvidia-smi -q -l 0 -d MEMORY&#xff1a;显示GPU特定信息&#xff1b; nvidia-smi -h&#xff1a;英伟达的帮助命令。…...

Open CASCADE学习| ​提取曲面的PCurve

PCurve这个概念&#xff0c;字面上来理解就是参数曲线&#xff08;Parametric Curve&#xff09;。参数空间曲线是在参数曲面的双参数空间中的二维样条曲线。 二维曲线定义的目的只有一个&#xff1a;pCurve&#xff0c;参数曲线。OCC采用参数法构建几何结构&#xff0c;所有的…...

GMS测试BTSfail-CVE-2022-20451

描述&#xff1a; 项目需要过GMS兼容性测试&#xff0c;BTS这块我们环境没有&#xff0c;送检之后出现了一个BTS的Alert&#xff0c;这个是必须要解决的。下面的warning可以不考虑。 这个是patch问题&#xff0c;根据代理提供的pdf文件找到一个id:为A-235098883的补丁&#xf…...

Vue学习笔记12--Vue3之setup/ref函数/reactive函数/Vue3响应式原理/reactive对比ref

一、拉开序幕的setup 理解&#xff1a;Vue3中一个新的配置项&#xff0c;值为一个函数。setup是所有Composition API(组合API&#xff09;表演的舞台。组件中所用到的&#xff1a;数据、方法等&#xff0c;均要配置在setup中。setup函数的两种返回值&#xff1a; 若返回一个对…...

座位预约|座位预约小程序|基于微信小程序的图书馆自习室座位预约管理系统设计与实现(源码+数据库+文档)

座位预约小程序目录 目录 基于微信小程序的图书馆自习室座位预约管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员服务端功能模块 2、学生微信端功能模块 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 …...

03 Redis之命令(基本命令+Key命令+String型Value命令与应用场景)

Redis 根据命令所操作对象的不同&#xff0c;可以分为三大类&#xff1a;对 Redis 进行基础性操作的命令&#xff0c;对 Key 的操作命令&#xff0c;对 Value 的操作命令。 3.1 Redis 基本命令 一些可选项对大小写敏感, 所以应尽量将redis的所有命令大写输入 首先通过 redis-…...

go语言函数进阶

1.变量作用域 全局变量 全局变量是定义在函数外部的变量&#xff0c;它在程序整个运行周期内都有效。 在函数中可以访问到全局变量。 package mainimport "fmt"//定义全局变量num var num int64 10func testGlobalVar() {fmt.Printf("num%d\n", num) /…...

Python编程技巧 – 函数参数

Python编程技巧 – 函数参数 Python Programming Skills - Functional Parameters 1. 函数的定义 函数有简明扼要的定义。 函数是一个代码块&#xff0c;仅在调用时运行。可以将数据&#xff08;称为参数&#xff09;传递到函数中。函数可以返回数据作为结果。 2. 函数的结…...

python222网站实战(SpringBoot+SpringSecurity+MybatisPlus+thymeleaf+layui)-帖子管理实现

锋哥原创的SpringbootLayui python222网站实战&#xff1a; python222网站实战课程视频教程&#xff08;SpringBootPython爬虫实战&#xff09; ( 火爆连载更新中... )_哔哩哔哩_bilibilipython222网站实战课程视频教程&#xff08;SpringBootPython爬虫实战&#xff09; ( 火…...

LabVIEW扫频阻抗测试系统

实现扫频阻抗法用于检测变压器绕组变形&#xff0c;结合了短路阻抗法和频响法的优点&#xff0c;但受限于硬件精度&#xff0c;尤其是50 Hz短路阻抗测试存在稳定性和准确性的问题。通过LabVIEW编程&#xff0c;控制宽频带信号发生器和高速采集卡&#xff0c;提高测试结果的稳定…...

C语言——指针进阶(四)

目录 一.前言 二.指针和数组笔试题解析 2.1 二维数组 2.2 指针笔试题 三.全部代码 四.结语 一.前言 本文我们将迎来指针的结尾&#xff0c;包含了二维数组与指针的试题解析。码字不易&#xff0c;希望大家多多支持我呀&#xff01;&#xff08;三连&#xff0b;关注&…...

Django介绍

一、介绍 Django是Python语言中的一个Web框架&#xff0c;Python语言中主流的web框架有Django、Tornado、Flask 等多种 优势&#xff1a;大而全&#xff0c;框架本身集成了ORM、模型绑定、模板引擎、缓存、Session等功能&#xff0c;是一个全能型框架&#xff0c;拥有自己的A…...

【idea】几个不错的idea插件让我码速又快了

目录 前言 Gradianto插件 jclasslib Bytecode viewer插件 Grep Console 插件 GenerateAllSetter 插件 GsonFormat 插件 JRebel and XRebel 插件 leetcode editor 插件 maven helper 插件 SequenceDiagram 插件 Statistic 插件 Translation 插件 前言 idea可以说是j…...

LabVIEW直流电机转速检测与控制

研究了使用LabVIEW软件和ELVIS实验平台来检测和控制直流电机的转速。通过集成光电传感器和霍尔传感器&#xff0c;实现了对电机转速的精确测量和调节。 系统组成&#xff1a;系统由NI ELVIS实验平台、光电传感器、霍尔传感器和直流电机组成。通过这些硬件元件&#xff0c;系统…...

༺༽༾ཊ—Unity之-05-抽象工厂模式—ཏ༿༼༻

首先创建一个项目&#xff0c; 在这个初始界面我们需要做一些准备工作&#xff0c; 建基础通用文件夹&#xff0c; 创建一个Plane 重置后 缩放100倍 加一个颜色&#xff0c; 任务&#xff1a;使用 抽象工厂模式 创建 人物与宠物 模型&#xff0c; 首先资源商店下载 人物与宠物…...

力扣面试题02.07-链表相交

链表相交 题目链接 解题思路&#xff1a; 题目可以确定如果相交&#xff0c;那么相交的部分一定是在链表的结尾部分第一步求得两条链表的长度第二步长度做差&#xff0c;将长的那条链表与短的那条链表后部分对其第三步遍历后面的部分&#xff0c;如果当前节点相等&#xff0c;…...

Java集合-ArrayList

集合就是一个保存数据的容器。在计算机中引入集合&#xff0c;是为了便于处理一组类似的数据。Java标准库自带的java.util包提供了集合相关的接口和实现类&#xff1a;Collection接口&#xff0c;它是除了Map接口外所有其他集合类的根接口。 Java的Java.uitl包主要提供以下三种…...

数据结构·单链表经典例题

1. 移除链表元素 OJ链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 本题是说给出一个链表的头节点head和一个整数val&#xff0c;如果发现节点中存的数据有val就删掉它&#xff0c;最后返回修改后的链表头节点地址 如果题目中没有明确…...