设计模式轻松学【十】适配器模式

简介: 在软件设计中也可能出现:需要开发的具有某种业务功能的组件在现有的组件库中已经存在,但它们与当前系统的接口规范不兼容,如果重新开发这些组件成本又很高,这时用适配器模式能很好地解决这些问题。

定义与特点

在现实生活中,经常出现两个对象因接口不兼容而不能在一起工作的例子,这时需要第三者进行适配。例如,讲中文的人同讲英文的人对话时需要一个翻译,用直流电的笔记本电脑接交流电源时需要一个电源适配器,用计算机访问照相机的 SD 内存卡时需要一个读卡器等。

image.png

  • 定义

    将一个类的接口转换成客户希望的另一个接口。适配器模式让那些接口不兼容的类可以一起工作。适配器就是一种适配中间件,它存在于不匹配的二者之间,用于连接二者,将不匹配变得匹配。

  • 参与角色

    • Target(目标接口):当前系统业务所期待的适配器接口类,它可以是抽象类或接口。
    • Adaptee(适配者类):被适配的角色,是一个已经存在的接口,这个接口需要我们适配才能使用,适配者类提供了客户希望使用但无法直接使用的业务方法。
    • Adapter(适配器类):实现Target,作为一个转换器,对Adaptee和Target进行适配。它是适配器模式的核心。
  • 结构类图

    适配器模式分为 类适配器模式 和 对象适配器模式。

    类适配器:采用继承的方式,静态的定义,耦合度比较高,较少使用。

    对象适配器:采用对象聚合的方式,耦合度低,常用。

    1. 类适配器模式

      image.png

    2. 对象适配器模式

      image.png

  • 模式代码示例

    1. 类适配器模式的代码如下

      package com.it235.adapter.clazz;
      //目标接口,客户端所期待调用的方法
      interface Target{
          public void request();
      }
      
      //适配者接口,客户端想调用但是又无法调用的方法
      class Adaptee{
          public void specificRequest(){       
              System.out.println("适配者中的业务代码被调用!");
          }
      }
      
      //类适配器类
      class ClassAdapter extends Adaptee implements Target{
          public void request(){
              specificRequest();
          }
      }
      
      //客户端代码
      public class ClassAdapterTest{
          public static void main(String[] args){
              System.out.println("类适配器模式测试:");
              Target target = new ClassAdapter();
              target.request();
          }
      }
      //运行结果
      类适配器模式测试:
      适配者中的业务代码被调用!
    2. 对象适配器模式的代码如下

      package com.it235.adapter.object;
      
      //目标接口
      interface Target{
          public void request();
      }
      
      //适配者接口
      class Adaptee{
          public void specificRequest(){       
              System.out.println("适配者中的业务代码被调用!");
          }
      }
      
      //对象适配器类
      class ObjectAdapter implements Target{
          private Adaptee adaptee;
          public ObjectAdapter(Adaptee adaptee){
              this.adaptee = adaptee;
          }
          public void request(){
              adaptee.specificRequest();
          }
      }
      
      //客户端代码
      public class ObjectAdapterTest{
          public static void main(String[] args){
              System.out.println("对象适配器模式测试:");
              Adaptee adaptee = new Adaptee();
              Target target = new ObjectAdapter(adaptee);
              target.request();
          }
      }
      //运行结果
      对象适配器模式测试:
      适配者中的业务代码被调用!

模式实现分析

电脑通过读卡器读取TF存储卡,在智能机刚出现的时候,手机中的内存卡是可卸载的,如果要下载歌曲或者电影,我们需要拔出该存储卡之后,通过读卡器去电脑上下载,现在我们模拟电脑读取SD卡和TF内存卡之间的适配关系。

需求:电脑可以直接读取SD卡(大型一点的卡),SD卡可以充当读卡器的作用读取小的TF卡。

  1. 计算机读取SD卡程序

    interface SDCard {
        //读取SD卡方法
        String readSD();
        //写入SD卡功能
        int writeSD(String msg);
    }
    
    //华为生产的SD卡
    class HuaWeiSDCard implements SDCard {
        
        @Override
        public String readSD() {
            return "读SD卡";  
        }
        
        @Override  
        public int writeSD(String msg) {      
            System.out.println("写SD卡");    
            return 1;   
        }
    }
    
    //计算机
    class Computer {    
         public String readSD(SDCard sdCard) {        
                return sdCard.readSD();    
         }
    }
    
    //客户进行插卡操作
    public class SDCardTest {
        public static void main(String[] args) {
            Computer computer = new Computer();        
            SDCard sdCard = new HuaWeiSDCard();       
            System.out.println(computer.readSD(sdCard));    
        }
    }
    

    一般笔记本电脑都支持直接读取SD卡,但不支持读取手机中的TF小卡,这里我们让SD卡充当读卡器的作用,将TF小卡放置到SD卡上就可以完成电脑对TF小卡的读取。这里的适配器就是SD卡。

  2. 创建TF卡对象

    //TF卡接口
    interface TFCard {    
        String readTF();    
        int writeTF(String msg);
    }
    //华为TF卡
    class HuaWeiTFCard implements TFCard {    
        @Override    
        public String readTF() {        
            return "读TF卡";   
        }    
        @Override    
        public int writeTF(String msg) {        
            System.out.println("写TF卡");     
            return 1;    
        }
    }

    此时TF卡我们拿到了,但是Computer类目前只支持读SD卡,Computer已经出厂了,无法再进行卡槽扩充更改,所以我们要赋予SD卡适配器的功能,让给SD卡适配TF卡。

  3. 加入适配器,将SD支持TF卡操作

    • 类适配模式

      创建适配器类,继承了被适配类,同时实现标准接口

      //类适配模式
      class SDAdapterTF extends HuaWeiTFCard implements SDCard {
          
          @Override    
          public String readSD() {        
              System.out.println("适配读取TF卡,充当转接作用");        
              return super.readTF();    
          }    
          @Override    
          public int writeSD(String msg) {        
              System.out.println("适配写入TF卡,充当转接作用");        
              return super.writeTF(msg);    
          }
      }
      
      //客户端调用
      public class ClassAdapterTest {
          public static void main(String[] args) {
              Computer computer = new Computer();        
              SDCard tfCardAdapterSD = new SDAdapterTF();        
              System.out.println(computer.readSD(tfCardAdapterSD));    
          }
      }

      该模式基于继承实现,不利于扩展,使用比较少

    • 对象适配模式

      创建适配器类,实现标准接口,将这个调用委托给实现新接口的对象来处理

      //对象适配模式
      class SDAdapterTF implements SDCard {
          
          private TFCard tfCard;    
          
          public SDAdapterTF(TFCard tfCard) {        
              this.tfCard = tfCard;    
          }
          
          @Override    
          public String readSD() {        
              System.out.println("适配读取TF卡,充当转接作用");        
              return tfCard.readTF();    
          }    
          @Override    
          public int writeSD(String msg) {        
              System.out.println("适配写入TF卡,充当转接作用");        
              return tfCard.writeTF(msg);    
          }
      }
      
      //客户端调用
      public class ClassAdapterTest {
          public static void main(String[] args) {
              Computer computer = new Computer();
              TFCard tfCard = new HuaWeiTFCard();      
              SDCard tfCardAdapterSD = new SDAdapterTF(tfCard);        
              System.out.println(computer.readSD(tfCardAdapterSD));    
          }
      }

      对象适配模式基于组合实现,依赖较弱,扩展性强

JDK中的案例

java.util.Arrays#asList()
java.io.InputStreamReader(InputStream)
java.io.OutputStreamWriter(OutputStream)

下面以InputStreamReaderOutputStreamWriter 类为例介绍适配器模式。
InputStreamReaderOutputStreamWriter分别继承ReaderWriter两个抽象类,但是要创建它们的对象必须在构造函数中传入一个InputStreamOutputStream的实例。

InputStreamReaderOutputStreamWriter也就是将InputStreamOutputStream适配到ReaderWriter

image.png

总结

  • 优点如下。

    • 客户端通过适配器可以透明地调用目标接口。
    • 复用了现存的类,程序员不需要修改原有代码而重用现有的适配者类。
    • 将目标类和适配者类解耦,解决了目标类和适配者类接口不一致的问题。

    其缺点是:对类适配器来说,更换适配器的实现过程比较复杂,过多使用会导致系统凌乱,追溯困难(内部转发导致,调用A适配成B)。

  • 适用场景

    • 系统需要使用一些现有的类,而这些类的接口(如方法名)不符合系统的需要,甚至没有这些类的源代码。
    • 想创建一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。
目录
相关文章
|
7月前
|
设计模式 前端开发 Java
【设计模式】【结构型模式】适配器模式(Adpter)
一、入门 什么是适配器模式? 适配器模式是Java中常用的结构型设计模式,它的核心作用就像现实中的电源转换器一样---让原本不兼容的两个接口能够协同工作。 为什么要用适配器模式? 假设我们需要在电商系
192 10
|
11月前
|
设计模式 Java 开发者
「全网最细 + 实战源码案例」设计模式——适配器模式
适配器模式(Adapter Pattern)是一种结构型设计模式,通过引入适配器类将一个类的接口转换为客户端期望的另一个接口,使原本因接口不兼容而无法协作的类能够协同工作。适配器模式分为类适配器和对象适配器两种,前者通过多重继承实现,后者通过组合方式实现,更常用。该模式适用于遗留系统改造、接口转换和第三方库集成等场景,能提高代码复用性和灵活性,但也可能增加代码复杂性和性能开销。
453 28
|
设计模式 Java
【设计模式】JAVA Design Patterns——Adapter(适配器模式)
【设计模式】JAVA Design Patterns——Adapter(适配器模式)
|
设计模式 JSON 前端开发
前端必须掌握的设计模式——适配器模式
适配器模式是一种结构型设计模式,用于使接口不兼容的对象能够相互合作。通过在客户端和系统之间引入一个“中间层”适配器,将不同类型的输入数据转换为系统能处理的标准格式,减轻系统的负担,提高扩展性和可维护性。例如,MacBook的扩展坞将多种接口(如HDMI、USB)转换为Type-C接口,实现多接口兼容。
|
设计模式 Java 程序员
Java设计模式-适配器模式(8)
Java设计模式-适配器模式(8)
114 2
|
设计模式 Java
Java设计模式之适配器模式
这篇文章详细讲解了Java设计模式中的适配器模式,包括其应用场景、实现方式及代码示例。
238 0
|
设计模式 XML 存储
【六】设计模式~~~结构型模式~~~适配器模式(Java)
文章详细介绍了适配器模式(Adapter Pattern),这是一种结构型设计模式,用于将一个类的接口转换成客户期望的另一个接口,使原本不兼容的接口能够一起工作,提高了类的复用性和系统的灵活性。通过对象适配器和类适配器两种实现方式,展示了适配器模式的代码应用,并讨论了其优点、缺点以及适用场景。
|
设计模式 Java
设计模式--适配器模式 Adapter Pattern
这篇文章介绍了适配器模式,包括其基本介绍、工作原理以及类适配器模式、对象适配器模式和接口适配器模式三种实现方式。
|
设计模式
适配器模式-大话设计模式
适配器模式-大话设计模式
|
设计模式 Go 数据处理
iLogtail设计模式问题之在iLogtail中,为何需要使用适配器模式
iLogtail设计模式问题之在iLogtail中,为何需要使用适配器模式

热门文章

最新文章