厚积薄发打卡Day33 :[kuangStudy] GoF23通俗易懂的设计模式之 <适配器模式>

前言:

视频教程:狂神说Java之通俗易懂的23种设计模式

什么是设计模式?

  • 设计模式(Design Pattern)是前辈们对代码开发经验的总结,是解决特定问题的一系列套路。
    它不是语法规定,而是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案==> 一种思维,一种态度,一种进步
  • 1995年,GoF(Gang of Four,四人组/四人帮)合作出版了《设计模式:可复用面向对象软件的基础》一书,共收录了23种设计模式,从此树立了软件设计模式领域的里程碑,人称 【GoF设计模式】
设计模式分类具体模式
创建型模式:
这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。
⌛单例模式、⌛工厂模式、⌛抽象工厂模式、⌛建造者模式、⌛原型模式
结构型模式:
这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。
⌛适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式
行为型模式:
这些设计模式特别关注对象之间的通信。
模板方法模、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式、访问者模式

适配器模式:

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

    • 举个例子:
      在这里插入图片描述
  • 角色分析

    刘伟大佬讲设计模式的文章,值得一看:不兼容结构的协调——适配器模式(一)

    • 在对象适配器模式结构图中包含如下几个角色:

      • Target(目标抽象类):目标抽象类定义客户所需接口,可以是一个抽象类或接口,也可以是具体类。
      • Adapter(适配器类):适配器可以调用另一个接口,作为一个转换器,对Adaptee和Target进行适配,适配器类是适配器模式的核心,在对象适配器中,它通过继承Target并关联一个Adaptee对象使二者产生联系。
      • Adaptee(适配者类):适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类一般是一个具体类,包含了客户希望使用的业务方法,在某些情况下可能没有适配者类的源代码。
    • 根据上述角色分析,结合例子可得:
      电脑要用过USB接口上网:

      • 电脑:Target(目标抽象类)
      • USB转接器:Adapter(适配器类)
      • 网线: Adaptee(适配者类)
  • 实现模式:

    • 类适配器:通过继承
    • 对象适配器:通过类作为属性进行组合

代码实例:

依旧是笔记本通过usb转接器上网的例子:

类适配器:

简单来说就是买了个自带网线的转接头:
在这里插入图片描述

//要被适配的类:网线类
public class Cable {

    public void surfing(){
        System.out.println("成功连接网线-->上网冲浪~");
    }
}
//接口转换器的抽象实现
public interface CableToUSB {

    //作用:处理请求,转接网线
    public void handleRequest();
}
//真正的网线适配器,比如华为牌子的适配器
//此处的类适配器,相当于买了个插着网线的转换器
public class Adapter extends Cable implements CableToUSB {

    @Override
    public void handleRequest() {
        super.surfing();//此时可以上网了
    }
}

有自带网线的转换器,这时自己买的网线用不上:

//客户端:想上网的具体实现
public class Computer {

    //usb需要一个转接器才能插上网线上网
    public void net(CableToUSB cableToUSB){
        //上网的具体实现,需要一个转接头:
        cableToUSB.handleRequest();
    }

    public static void main(String[] args) {
        //电脑:
        Computer computer = new Computer();
        //适配器:
        Adapter adapter = new Adapter();
        //网线:
        Cable cable = new Cable();//自备的网线用不上

        //真正用电脑上网,此时usb插上了一个自带网线的转换器
        computer.net(adapter);

        //成功上网:
        //成功连接网线-->上网冲浪~
    }
}

对象适配器:

相当于买了个 可拔插式的转接器,需要用自己的网线

在这里插入图片描述

//要被适配的类:网线类
public class Cable {

    public void surfing(){
        System.out.println("成功连接网线-->上网冲浪~");
    }
}
//接口转换器的抽象实现
public interface CableToUSB {

    //作用:处理请求,转接网线
    public void handleRequest();
}

网线与转换器接口都不变👆

//真正的网线适配器,比如华为牌子的适配器
public class Adapter  implements CableToUSB {
    //此处进行组合
    private Cable cable;

    public Adapter(Cable cable) {
        this.cable = cable;
    }

    @Override
    public void handleRequest() {
        cable.surfing();//此时可以上网了
    }
}
//客户端:想上网的具体实现
public class Computer {

    //usb需要一个转接器才能插上网线上网
    public void net(CableToUSB cableToUSB){
        //上网的具体实现,需要一个转接头:
        cableToUSB.handleRequest();
    }

    public static void main(String[] args) {
        //电脑:
        Computer computer = new Computer();
        //网线:
        Cable cable = new Cable();
        //适配器:
        //此时的适配器需要插上一个网线才能用:
        Adapter adapter = new Adapter(cable);

        //真正用电脑上网,
        computer.net(adapter);

        //成功上网:
        //成功连接网线-->上网冲浪~
    }
}

小结:

  • 对象适配器优点

    • 一个对象适配器可以把多个不同的适配者适配到同一个目标
    • 可以适配一个适配者的子类,由于适配器和适配者之间是关联关系,根据“里氏代换原则”,适配者的子类也可通过该适配器进行适配.
  • 类适配器缺点

    • 对于Java,C#等不支持多重类继承的语言,一次最多只能适配一个适配者类,不能同时适配多个适配者;
    • 在Java,C#等语言中,类适配器模式中的目标抽象类只能为接口,不能为类,其使用有一定的局限性。
  • 适用场景

    • 系统需要使用一些现有的类,而这些类的接口(如方法名)不符合系统的需要,甚至没有这些类的源
      代码.

    • 想创建一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作.

    • 因此适配器模式又称 弥补形模式

      怪不得在平时的二开工作中看到老大用过

应用案例:

  1. io流中的InputStreamReader 和 OutputStreamWriter

    设计模式在JDK中的应用

    1. java.io.InputStreamReader(InputStream)

      将输入的字节流转换为字符流

      public InputStreamReader(InputStream in) {
          super(in);
          try {
              sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object
          } catch (UnsupportedEncodingException e) {
              // The default encoding should always be available
              throw new Error(e);
          }
      }
      
    2. java.io.OutputStreamWriter(OutputStream)

  2. 在SpringMVC中的DispatcherServlet 中的doDispatch() 有使用

    适配器模式在Spring源码中的应用

    适配器模式在 SpringMVC 中的经典使用体现在它的核心方法 doDispatch 方法中,再来看一个 Spring MVC 中的 HandlerAdapter 类,它也有多个子类,类图如下。

    在这里插入图片描述

    设计模式|适配器模式使用案例、适配器模式在源码中的应用

    位于org.springframework.web.servlet包中的DispatcherServlet是servlet接口的实现类,作用是处理请求并返回结果。在servlet容器接收到一个请求时,servlet容器会针对这个请求创建一个servletRequest和servletRespones对象,相应的处理方法会通过servletRequest中携带的参数对应处理请求,再通过servletRespones对象商城请求的响应结果。

    DispatcherServlet类的doDispatch方法是处理请求的核心逻辑,截取部分内容如下

    try {
        //对请求做类型转换
        processedRequest = checkMultipart(request);
        multipartRequestParsed = (processedRequest != request);
    
        // 根据请求信息找到相应的Handler
        mappedHandler = getHandler(processedRequest);
        if (mappedHandler == null) {
            noHandlerFound(processedRequest, response);
            return;
        }
    
        // 根据handleru想你找相应的HandlerAdapter
        HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    }
    
  3. Collections 的 enumeration 方法

    适配器模式在开源代码中的应用

    public static <T> Enumeration<T> enumeration(final Collection<T> c) {
       return new Enumeration<T>() {
           private final Iterator<T> i = c.iterator();
    
           public boolean hasMoreElements() {
               return i.hasNext();
           }
        public T nextElement() {
               return i.next();
           }
       };
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值