【设计模式——学习笔记】23种设计模式——适配器模式Adapter(原理讲解+应用场景介绍+案例介绍+Java代码实现)

这篇具有很好参考价值的文章主要介绍了【设计模式——学习笔记】23种设计模式——适配器模式Adapter(原理讲解+应用场景介绍+案例介绍+Java代码实现)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

介绍

生活中的案例

不同国家的插座不同,出国旅游充电器不能直接使用,可以通过使用多功能转换插头来辅助使用

基础介绍

  • 适配器模式将某个类的接口转换成客户端期望的另一个接口表示,主的目的是兼容性,让原本因接口不匹配不能一起工作的两个类可以协同工作。其别名为包装器(Wrapper)

    适配器模式属于结构型模式(没有产生什么新对象,只是结构的一些调整,让类与类之间可以协调工作)

工作原理

  • 将一个类的接口转换成另一种接口,目的是让原本接口不兼容的类可以兼容
  • 从用户的角度看不到被适配者(A调用B,中间有个adpater,B属于被适配者),是解耦的
  • 用户调用适配器转化出来的目标接口方法,适配器再调用被适配者的相关接口方法
  • 用户收到反馈结果,感觉只是和目标接口交互

【设计模式——学习笔记】23种设计模式——适配器模式Adapter(原理讲解+应用场景介绍+案例介绍+Java代码实现),设计模式,java,设计模式,学习,适配器模式

分类

  • 类适配器模式
  • 对象适配器模式
  • 接口适配器模式

应用场景

很多时候,我们加入项目组的时候,项目已经有一定的代码量了,或者部分代码已经在生产环境上面使用了,这些方法已经经过测试,在我们开发新的项目时,可以将这些类作为组件重复利用,但是可能没办法直接调用,需要我们使用适配器模式来让这些方法适配我们的现有项目。

疑问:直接修改之前的类不就可以了吗,为啥要使用适配器模式?答:之前的类都比较完善了,如果在上面改乱了,出了bug不好调试,但是如果使用了适配器模式,那出了bug就知道是适配器的问题。此外,在Adapter模式中,并非一定需要现成的代码。只要知道现有类的功能,就可以编写出新的类。

适配器模式还能用于做新旧版本的兼容,可以让新版本扮演Adaptee 角色,旧版本扮演Target角色。接着编写一个扮演Adapter 角色的类,让它使用新版本的类来实现旧版本的类中的方法。如下图

【设计模式——学习笔记】23种设计模式——适配器模式Adapter(原理讲解+应用场景介绍+案例介绍+Java代码实现),设计模式,java,设计模式,学习,适配器模式

案例

类适配器模式

例1

介绍
  • Adapter类,通过继承src类,实现 dst 类接口,完成src->dst的适配
  • 如生活中的小例子:充电器本身相当于Adapter,220V交流电相当于src(即被适配者),我们的dst(即目标)是5V直流电
类图

【设计模式——学习笔记】23种设计模式——适配器模式Adapter(原理讲解+应用场景介绍+案例介绍+Java代码实现),设计模式,java,设计模式,学习,适配器模式

代码实现

【被适配的类】

package com.atguigu.adapter.classadapter;

/**
 * 被适配的类
 */
public class Voltage220V {
   /**
    * 输出220V的电压
    * @return
    */
   public int output220V() {
      int src = 220;
      System.out.println("电压=" + src + "伏");
      return src;
   }
}

适配接口

package com.atguigu.adapter.classadapter;


/**
 * 适配接口
 */
public interface IVoltage5V {
   public int output5V();
}

【适配器】

package com.atguigu.adapter.classadapter;

/**
 * 适配器类 将220V转化为5V
 */
public class VoltageAdapter extends Voltage220V implements IVoltage5V {

   @Override
   public int output5V() {
      //获取到220V电压
      int srcV = output220V();
      //转成 5v(降压)
      int dstV = srcV / 44 ;
      return dstV;
   }

}

【手机类】

package com.atguigu.adapter.classadapter;

public class Phone {

   /**
    * 手机充电方法
    * @param iVoltage5V
    */
   public void charging(IVoltage5V iVoltage5V) {
      if(iVoltage5V.output5V() == 5) {
         System.out.println("电压为5V, 可以充电~~");
      } else if (iVoltage5V.output5V() > 5) {
         System.out.println("电压过高, 不能充电~~");
      }
   }
}

【客户端:用户给手机充电】

package com.atguigu.adapter.classadapter;

public class Client {

   public static void main(String[] args) {
      System.out.println(" === 类适配器模式 ====");
      Phone phone = new Phone();
      phone.charging(new VoltageAdapter());
   }

}

【运行】

 === 类适配器模式 ====
电压=220伏
电压为5V, 可以充电~~

Process finished with exit code 0
优缺点分析

【优点】

  • 由于其继承了src类,所以它可以根据需求重写src类的方法,使得Adapter的灵活性增强了

【缺点】

  • Java是单继承机制,所以类适配器需要继承src类这一点算是一个缺点(之前的七大原则分析过,使用继承不好),因为这要求dst必须是接口,有一定局限性
  • src类的方法在Adapter中都会暴露出来,也增加了使用的成本(如果方法很多,调用起来就麻烦了)

例2

类图

【设计模式——学习笔记】23种设计模式——适配器模式Adapter(原理讲解+应用场景介绍+案例介绍+Java代码实现),设计模式,java,设计模式,学习,适配器模式

代码实现

【src】

package com.atguigu.adapter.Sample1;

public class Banner {
    private String string;

    public Banner(String string) {
        this.string = string;
    }

    public void showWithParen() {
        System.out.println("(" + string + ")");
    }

    public void showWithAster() {
        System.out.println("*" + string + "*");
    }
}

【dst】

package com.atguigu.adapter.Sample1;

public interface Print {
    public abstract void printWeak();
    public abstract void printStrong();
}

【适配器】

package com.atguigu.adapter.Sample1;

public class PrintBanner extends Banner implements Print {
    public PrintBanner(String string) {
        super(string);
    }
    public void printWeak() {
        showWithParen();
    }
    public void printStrong() {
        showWithAster();
    }
}

【客户端】

package com.atguigu.adapter.Sample1;

public class Main {
    public static void main(String[] args) {
        Print p = new PrintBanner("Hello");
        p.printWeak();
        p.printStrong();
    }
}

【运行】

(Hello)
*Hello*

Process finished with exit code 0

【分析】

对Main类的代码而言,Banner类、showWithParen方法和showWithAster 方法被完全隐藏起来了。这就好像笔记本电脑只要在直流12伏特电压下就能正常工作,但它并不知道这12伏特的电压是由适配器将100伏特交流电压转换而成的。Main类并不知道PrintBanner类是如何实现的,这样就可以在不用对Main类进行修改的情况下改变PrintBanner类的具体实现。

对象适配器模式(常用方式)

例1

介绍
  • 基本思路和类的适配器模式相同,只是将Adapter类作修改,不是继承src类,而是持有src类的实例(聚合src类),以解决兼容性的问题。 即:持有 src类,实现 dst 类接口,完成src->dst的适配
  • 根据“合成复用原则”,在系统中尽量使用关联关系来替代继承关系
  • 对象适配器模式是适配器模式常用的一种
类图

【设计模式——学习笔记】23种设计模式——适配器模式Adapter(原理讲解+应用场景介绍+案例介绍+Java代码实现),设计模式,java,设计模式,学习,适配器模式

代码实现

【适配器类】

package com.atguigu.adapter.objectadapter;

/**
 * 适配器类
 */
public class VoltageAdapter implements IVoltage5V {

    /**
     * 关联关系-聚合
     */
    private Voltage220V voltage220V;


    /**
     * 通过构造器,传入一个 Voltage220V 实例
     *
     * @param voltage220v
     */
    public VoltageAdapter(Voltage220V voltage220v) {
        this.voltage220V = voltage220v;
    }

    @Override
    public int output5V() {
        int dst = 0;
        if (null != voltage220V) {
            //获取220V 电压
            int src = voltage220V.output220V();
            System.out.println("使用对象适配器,进行适配~~");
            dst = src / 44;
            System.out.println("适配完成,输出的电压为=" + dst);
        }
        return dst;
    }

}

【客户端:用户给手机充电】

package com.atguigu.adapter.objectadapter;

public class Client {

   public static void main(String[] args) {
      // TODO Auto-generated method stub
      System.out.println(" === 对象适配器模式 ====");
      Phone phone = new Phone();
      phone.charging(new VoltageAdapter(new Voltage220V()));
   }

}

其他类和类适配器模式的一致

优缺点分析

【优点】

  • 对象适配器和类适配器其实算是同一种思想,只不过实现方式不同。根据合成复用原则,使用组合替代继承,所以它解决了类适配器必须继承src的局限性问题,也不再要求dst必须是接口
  • 使用成本更低,更灵活

例2

代码实现

【dst】

package com.atguigu.adapter.Sample2;

public abstract class Print {
    public abstract void printWeak();
    public abstract void printStrong();
}

【适配器】

package com.atguigu.adapter.Sample2;

public class PrintBanner extends Print {
    private Banner banner;
    public PrintBanner(String string) {
        this.banner = new Banner(string);
    }
    public void printWeak() {
        banner.showWithParen();
    }
    public void printStrong() {
        banner.showWithAster();
    }
}

其他两个类的和类适配器模式的例2的代码一致

接口适配器模式

介绍

  • 一些书籍称为:适配器模式(Default Adapter Pattern)或缺省适配器模式
  • 当不需要全部实现接口提供的方法时,可先设计一个抽象类实现接口,并为该接口中每个方法提供一个默认实现(空方法),那么该抽象类的子类可有选择地覆盖父类的某些方法来实现需求
  • 适用于不想使用一个接口所有的方法的情况

【设计模式——学习笔记】23种设计模式——适配器模式Adapter(原理讲解+应用场景介绍+案例介绍+Java代码实现),设计模式,java,设计模式,学习,适配器模式
【设计模式——学习笔记】23种设计模式——适配器模式Adapter(原理讲解+应用场景介绍+案例介绍+Java代码实现),设计模式,java,设计模式,学习,适配器模式

【设计模式——学习笔记】23种设计模式——适配器模式Adapter(原理讲解+应用场景介绍+案例介绍+Java代码实现),设计模式,java,设计模式,学习,适配器模式

类图

【设计模式——学习笔记】23种设计模式——适配器模式Adapter(原理讲解+应用场景介绍+案例介绍+Java代码实现),设计模式,java,设计模式,学习,适配器模式

代码实现

【接口】

package com.atguigu.adapter.interfaceadapter;

public interface Interface4 {
   public void m1();
   public void m2();
   public void m3();
   public void m4();
}

【抽象类:适配器】

package com.atguigu.adapter.interfaceadapter;

/**
 * 在AbsAdapter 我们将 Interface4 的方法进行默认实现(空实现)
 */
public abstract class AbsAdapter implements Interface4 {

    @Override
    public void m1() {

    }

    @Override
    public void m2() {

    }

    @Override
    public void m3() {

    }

    @Override
    public void m4() {

    }
}

【客户端:重写抽象类的方法】

package com.atguigu.adapter.interfaceadapter;

public class Client {
   public static void main(String[] args) {

      AbsAdapter absAdapter = new AbsAdapter() {
         /**
          * 只需要去覆盖我们 需要使用 接口方法
          */
         @Override
         public void m1() {
            System.out.println("使用了m1的方法");
         }
      };

      absAdapter.m1();
   }
}

登场角色

  • Target(对象):负责定义所需的方法,如需要能提供5v电压的方法
  • Adaptee(被适配):该角色持有既定方法,如有一个方法可以提供220v电压
  • Adapter(适配):使用Adaptee角色的方法来满足Target角色的需求
  • Client(请求者):负责使用 Target 角色所定义的方法来做事,如使用5V电压给手机充电

类图

类适配器模式

【设计模式——学习笔记】23种设计模式——适配器模式Adapter(原理讲解+应用场景介绍+案例介绍+Java代码实现),设计模式,java,设计模式,学习,适配器模式

对象适配器模式

【设计模式——学习笔记】23种设计模式——适配器模式Adapter(原理讲解+应用场景介绍+案例介绍+Java代码实现),设计模式,java,设计模式,学习,适配器模式

适配器模式在SpringMvc中的应用

  • SpringMvc中的HandlerAdapter使用了适配器模式

【设计模式——学习笔记】23种设计模式——适配器模式Adapter(原理讲解+应用场景介绍+案例介绍+Java代码实现),设计模式,java,设计模式,学习,适配器模式

【设计模式——学习笔记】23种设计模式——适配器模式Adapter(原理讲解+应用场景介绍+案例介绍+Java代码实现),设计模式,java,设计模式,学习,适配器模式

【设计模式——学习笔记】23种设计模式——适配器模式Adapter(原理讲解+应用场景介绍+案例介绍+Java代码实现),设计模式,java,设计模式,学习,适配器模式

【设计模式——学习笔记】23种设计模式——适配器模式Adapter(原理讲解+应用场景介绍+案例介绍+Java代码实现),设计模式,java,设计模式,学习,适配器模式

类图

【设计模式——学习笔记】23种设计模式——适配器模式Adapter(原理讲解+应用场景介绍+案例介绍+Java代码实现),设计模式,java,设计模式,学习,适配器模式

模拟实现

【Controller】

package com.atguigu.spring.springmvc;

/**
 * 多种Controller实现
 */
public interface Controller {

}

//-----------------针对不同的请求,有多种不同的controller------------------------
class HttpController implements Controller {
   public void doHttpHandler() {
      System.out.println("http...");
   }
}

class SimpleController implements Controller {
   public void doSimplerHandler() {
      System.out.println("simple...");
   }
}

class AnnotationController implements Controller {
   public void doAnnotationHandler() {
      System.out.println("annotation...");
   }
}

【适配器】

package com.atguigu.spring.springmvc;

/**
 * 定义一个Adapter接口
 */
public interface HandlerAdapter {
    public boolean supports(Object handler);

    public void handle(Object handler);
}

//-------------------多种适配器类-------------------------

class SimpleHandlerAdapter implements HandlerAdapter {

    public void handle(Object handler) {
        ((SimpleController) handler).doSimplerHandler();
    }

    /**
     * 判断是否支持该handler
     * @param handler
     * @return
     */
    public boolean supports(Object handler) {
        return (handler instanceof SimpleController);
    }

}

class HttpHandlerAdapter implements HandlerAdapter {

    public void handle(Object handler) {
        ((HttpController) handler).doHttpHandler();
    }

    public boolean supports(Object handler) {
        return (handler instanceof HttpController);
    }

}

class AnnotationHandlerAdapter implements HandlerAdapter {

    public void handle(Object handler) {
        ((AnnotationController) handler).doAnnotationHandler();
    }

    public boolean supports(Object handler) {

        return (handler instanceof AnnotationController);
    }

}

【servlet】

package com.atguigu.spring.springmvc;

import java.util.ArrayList;
import java.util.List;

public class DispatchServlet {

   /**
    * 组合所有适配器
    */
   public static List<HandlerAdapter> handlerAdapters = new ArrayList<HandlerAdapter>();

   public DispatchServlet() {
      handlerAdapters.add(new AnnotationHandlerAdapter());
      handlerAdapters.add(new HttpHandlerAdapter());
      handlerAdapters.add(new SimpleHandlerAdapter());
   }

   public void doDispatch() {

      // 此处模拟SpringMVC从request取handler的对象,
      // 适配器可以获取到希望的Controller
       HttpController controller = new HttpController();
      // AnnotationController controller = new AnnotationController();
      //SimpleController controller = new SimpleController();
      // 得到对应适配器
      HandlerAdapter adapter = getHandler(controller);
      // 通过适配器执行对应的controller对应方法
      adapter.handle(controller);

   }

   /**
    * 根据controller返回对应的适配器
    * @param controller
    * @return
    */
   public HandlerAdapter getHandler(Controller controller) {
      //遍历:根据得到的controller(handler), 返回对应适配器
      for (HandlerAdapter adapter : this.handlerAdapters) {
         if (adapter.supports(controller)) {
            return adapter;
         }
      }
      return null;
   }

   public static void main(String[] args) {
      new DispatchServlet().doDispatch(); // http...
   }

}

分析

  • 适配器的价值:controller变化了,适配器也会跟着变化,最终调用的方法也不同
  • 扩展Controller 时,只需要增加一个适配器类就完成了SpringMVC的扩展了
  • 如果不使用适配器:可以看到处理器的类型不同,有多重实现方式,那么调用方式就不是确定的,如果需要直接调用Controller方法,需要调用的时候就得不断是使用if else来进行判断是哪一种子类然后执行。那么如果后面要扩展Controller,就得修改原来的代码,这样违背了OCP原则

【设计模式——学习笔记】23种设计模式——适配器模式Adapter(原理讲解+应用场景介绍+案例介绍+Java代码实现),设计模式,java,设计模式,学习,适配器模式文章来源地址https://www.toymoban.com/news/detail-605061.html

总结

  • 类适配器:以类给到,在Adapter里,就是将src当做类,继承
  • 对象适配器: 以对象给到,在Adapter里,将src作为一个对象,持有(聚合)
  • 接口适配器: 以接口给到,在Adapter里,将src作为一个接口,实现
  • Adapter模式最大的作用是将原本不兼容的接口融合在一起工作
  • 实际开发中,实现起来不拘泥于上述三种经典形式

文章说明

  • 本文章为本人学习尚硅谷的学习笔记,文章中大部分内容来源于尚硅谷视频(点击学习尚硅谷相关课程),也有部分内容来自于自己的思考,发布文章是想帮助其他学习的人更方便地整理自己的笔记或者直接通过文章学习相关知识,如有侵权请联系删除,最后对尚硅谷的优质课程表示感谢。
  • 本人还同步阅读《图解设计模式》书籍(图解设计模式/(日)结城浩著;杨文轩译–北京:人民邮电出版社,2017.1),进而综合两者的内容,让知识点更加全面

到了这里,关于【设计模式——学习笔记】23种设计模式——适配器模式Adapter(原理讲解+应用场景介绍+案例介绍+Java代码实现)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 学习设计模式之适配器模式,但是宝可梦

    作者在准备秋招中,学习设计模式,做点小笔记,用宝可梦为场景举例,有错误欢迎指出。 代码同步更新到 github ,要是点个Star您就是我的神 意图:将一个类的接口转换成客户希望的另一个接口 主要解决:把现有对象放到新环境里,而新环境要求的接口,现有对象不满足 何

    2024年02月11日
    浏览(36)
  • 设计模式-适配器模式

    在我们生活中,插座输出的电源都是220V的,而我们手机充电需要的电压基本都是5V的。我们不能直接用220V的电压来给手机充电,也不能说专门有线路来提供5V的电压。所以就有了充电器,充电器可以将220V的电压转为5V的电压,这样我们就方便太多了。 上面所说的充电器其实就

    2024年02月08日
    浏览(35)
  • 【设计模式】适配器模式

    适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。 这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。举个真实的例子,读卡器是作为内存卡和笔记本之间的适配器。

    2024年02月12日
    浏览(50)
  • 设计模式——适配器模式

    说起适配器其实在我们的生活中是非常常见的,比如:学校的宿舍的电压都比较低,而有的学生想使用大功率电器,宿舍的就会跳闸,然而如果你使用一个适配器(变压器)就可以使用了(温馨提示宿舍使用大功率电器不太安全,容易引起火灾,希望大家谨慎使用)。 又比如

    2024年02月12日
    浏览(45)
  • 设计模式--适配器模式

    目录 基本介绍 工作原理 类适配模式 介绍 应用实例介绍 类适配器模式注意事项和细节 对象适配模式 介绍 对象适配器模式注意事项和细节 接口适配器模式 介绍 适配器模式的注意事项和细节  (1) 适配器模式(Adapter Pattern) 将某个类的接口转换成客户端期望的另一个接口表示

    2023年04月26日
    浏览(30)
  • 【设计模式】使用适配器模式做补偿设计

    适配器模式是一种 结构型设计模式 ,它提供了一个中间层,通过这个中间层,客户端可以使用统一的接口与具有不同接口的类进行交互,也就是说,将一个接口转换成客户期望的另一个接口,使得原本不兼容的接口能够协同工作。 举个现实中的例子,我们现在的很多轻薄笔

    2024年02月22日
    浏览(32)
  • 设计模式四:适配器模式

    1、适配器模式的理解 适配器模式可以理解为有两个现成的类Adaptee和Target,它们两个是不能动的,要求必须使用B这个类来实现一个功能,但是A的内容是能复用的,这个时候我们需要编写一个转换器 适配器模式 Adaptee:被适配者,现有的接口或者类; Adapter:适配器类,适配器

    2024年02月22日
    浏览(35)
  • 《设计模式》之适配器模式

    把一个类的接口转换成客户端所期待的另一种接口,从而使原接口不匹配而无法再一起工作的两个类能在一起工作。 在软件系统中,由于应用环境的变化,常常需要将“一些现存的对象”放在新的环境中应用,但是新环境要求的接口是这些现存对象所不能满足的。 如何应对

    2024年02月09日
    浏览(38)
  • 设计模式-- 3.适配器模式

    将一个类的接口转换成客户希望的另外一个接口。使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 请求者(client):客户端角色,需要使用适配器的对象,不需要关心适配器内部的实现,只对接目标角色。 目标角色(Target):目标角色,和client直接对接,定义

    2024年01月18日
    浏览(49)
  • 设计模式 06 适配器模式

    适配器模式(Adapter Pattern)属于 结构型 模式 结构型 模式关注如何将现有的类或对象组织在一起形成更加强大的结构。 在生活中,我们经常遇到这样的一个问题:轻薄笔记本通常只有 type-c 或者 usb-a 接口,没有网口。但日常使用中是往往需要连接网口上网的,这时想到的第

    2024年02月11日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包