实用的设计模式08——适配器模式

适配器的单词是Adapter,我们在开发时经常碰到叫做XxxAdapter的类,此时一般就是使用了适配器模式,适配器模式是非常常用,本文就对适配器模式做一个简单的介绍

1、真实开发场景的问题引入

假设现系统有一个日志接口,但是其实现性能比较低下,开发者想换一个高性能的日志框架时,遇到了新的框架和原先的接口不兼容的问题,这个时候应该怎么办?如何让新的日志框架适配原先的日志接口。

其实在不考虑设计模式的情况下,也可以想到解决方式,那就是在原先的接口实现中,使用新框架的接口和方法实现原来的功能。

但是因为使用的是框架,所以修改之前的实现不是个好办法,比较麻烦,此时就可以考虑适配器模式。

2、适配器模式讲解

适配器模式就是在两个层不兼容是采取的方案,简单说就是再加一个层。

2.1 核心类及类图

在这里插入图片描述
对于图中的Client,原先使用的FormerImpl的实例,现在想使用Adaptee的对象,没法直接使用因为接口已经固定了,代码中也都使用的是FormerImpl,不可能再去修改代码,所以定义一个Adapter对象,作为一个中间层,向Client提供Adaptee的功能。

2.2 基本代码

  • Target.java
public interface LogFace {
    
    
    void logInfo(String info);
}
  • FormerImpl.java
public class FormerImpl implements LogFace{
    
    
    @Override
    public void logInfo(String info) {
    
    
        System.out.println(info);
    }
}
  • Adaptee.java
@Slf4j
public class Adaptee {
    
    
    public void logInfo(String info){
    
    
        log.info("高性能日志实现"+info);
    }
}
  • Adapter.java
public class Adapter implements LogFace{
    
    
    private Adaptee adaptee = new Adaptee();
    @Override
    public void logInfo(String info) {
    
    
        adaptee.logInfo(info);
    }
}

  • LogFactory.java:使用工厂方法获取日志门对象
public class LogFactory {
    
    
	//更换日志实现,只需要在此处返回new Adapter的对象返回即可
    private static LogFace logFace = new Adapter();
    public static LogFace getInstance(){
    
    
        return logFace;
    }
}
  • Client.java
public class Client {
    
    
    public static void main(String[] args) {
    
    
        LogFace logFace = LogFactory.getInstance();
        logFace.logInfo("打印日志");
    }
}

注意:在实例代码中添加一个工厂方法,用于创建日志门面接口(LogFace)的实现对象,与更换日志实现之前相比,客户端代码没有任何改变。

3、利用适配器模式解决问题

见示例代码。

4、适配器模式的应用实例

适配器模式一个最典型的应用就是在SpringMVC中,HandlerAdapter就是扮演的适配器的角色。
在这里插入图片描述
当收到客户端请求时,DispatcherServlet首先根据请求的URL等从处理器映射器(HandlerMapping)中找是否有对应的处理器,然后交给对应的HandlerAdapter去执行其中的处理请求的方法。其中:

  • Target:HandlerAdapter接口扮演的适配器模式中的Target的角色,所有的适配器必须实现这个接口中。
  • Adapter:HandlerAdapter具体的实现类就是该模式中的Adapter,真正执行对应类型请求的处理方法。
  • Adaptee:Adaptee是Controller,例如@Controller, @RestController标注的类
  • Client:客户端就是SpringMVC框架。当请求到达时,它根据控制器的类型使用适当的HandlerAdapter。然后,HandlerAdapter调用控制器的方法来处理请求并产生响应。

注意:
这里的模式使用思路和上面说的不太一样,这里的Adaptee有很多(Controller一般是有很多),所以更多是为了适配不同的Controller去进行统一的处理器方法执行,和JDBC接口一样的作用。

但是本质就是加一层,屏蔽差异。所以本身面向接口编程就有点适配器模式的味道在里面了。

5、总结

5.1 解决的问题

主要解决在软件系统中,常常要将一些"现存的对象"放到新的环境中,而新环境要求的接口是现对象不能满足的。

5.2 使用场景

  1. 系统需要使用现有的类,而此类的接口不符合系统的需要。
  2. 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作,这些源类不一定有一致的接口
  3. 通过接口转换,将一个类插入另一个类系中。(比如老虎和飞禽,现在多了一个飞虎,在不增加实体的需求下,增加一个适配器,在里面包容一个虎对象,实现飞的接口。)

5.3 优缺点

  • 优点:(1)可以让任何两个没有关联的类一起运行。 (2)提高了类的复用。 (3)增加了类的透明度。 (4)灵活性好。
  • 缺点 (1)过多地使用适配器,会让系统非常零乱,不易整体进行把握。例如看到的是这个类,但实际执行的是另一个类。(2)由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。

参考:
[1] 一次性搞懂设计模式–适配器模式 - 掘金 (juejin.cn)

[2] 适配器模式 | 菜鸟教程 (runoob.com)

[3] 秒懂设计模式之适配器模式(Adapter Pattern) - 知乎 (zhihu.com)

[4] Spring中的设计模式之适配器模式 - 知乎 (zhihu.com)

猜你喜欢

转载自blog.csdn.net/baidu_40120883/article/details/131880938