秒懂设计模式之适配器模式(Adapter Pattern)

Posted ShuSheng007

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了秒懂设计模式之适配器模式(Adapter Pattern)相关的知识,希望对你有一定的参考价值。

[版权申明] 非商业目的注明出处可自由转载
博文地址:https://blog.csdn.net/ShuSheng0007/article/details/116161690
出自:shusheng007

设计模式汇总篇,一定要收藏:

永不磨灭的设计模式(有这一篇真够了,拒绝标题党)

概述

由于面向对象程序设计本身就是从实际生活中汲取的灵感,将大千世界抽象到程序设计领域,所以所有的设计模式都是可以在日常生活中感受的到的。例如适配器模式,这个在日常生活中就太普遍了。
例如我们程序员经常遇到的电脑上提供的端口与要插入的接头匹配不上,而我们则可以通过一个中间的适配器将两边连接起来。

这个设计模式在日常开发中出镜率极高,关键还不难,所以兄弟们一定要掌握啊。

类型

结构型(structural)

难度

1颗星

定义

将一个接口转换为客户端所期待的接口,从而使两个接口不兼容的类可以在一起工作

适配器模式还有个别名叫:Wrapper(包装器),顾名思义就是将目标类用一个新类包装一下,相当于在客户端与目标类直接加了一层。IT世界有句俗语:没有什么问题是加一层不能解决的

使用场景

  • 当需要使用一个现存的类,但它提供的接口与我们系统的接口不兼容,而我们还不能修改它时
  • 当多个团队独立开发系统的各功能模块,然后组合在一起,但由于某些原因事先不能确定接口时。(别和我说这不可能,这太tm可能了)

UML类图

照例先上一张俺手撕的UML类图
在这里插入图片描述
从上图可见,适配器模式只有3个角色

  • Target

是一个接口,它是我们客户端使用的目标接口

  • Adaptee

我们想要使用的接口与Target不兼容的类,它可以是一个接口,也可以是一个类。

  • Adapter

适配器类,此模式的核心。它需要实现目标接口Target,而且必须要引用Adaptee,因为我们要在此类中包装Adaptee的功能

实例

最近王二狗工作上遇到了一件非常不开心的事:由于老项目中的日志系统非常粗糙,导致他debug时候非常吃力,为此都加了好几次班了,媳妇都不高兴了。某天,二狗又一次披星戴月的回到家中,蹑手蹑脚脱了衣服慢慢爬上床时,此时只听的床头那边幽幽的传来一声抱怨:二狗,你天天忙着调试bug,你就不担心你媳妇被隔壁老王调试了?

二狗深感不安,决定彻底扭转这个不利的局面。于是他调研了一个非常棒的三方开源日志库来改进项目的log系统,但是此开源库与项目中接口不兼容,这几乎是肯定的,所以王二狗又一次展现出了其高超的程序设计能力,精准的采用了适配器模式来完成这个功能。

第一,确定目标接口

系统原来的日志接口如下

public interface LogFactory {
    void debug(String tag,String message);
}

第二,三方库接口及实现

下面是第三方库提供的日志功能,但是其接口与二狗他们系统目前使用的不兼容。

public interface NbLogger {
    void d(int priority, String message, Object ... obj);
}
//具体提供日志功能的实现类
public class NbLoggerImp implements NbLogger {
    @Override
    public void d(int priority, String message, Object... obj) {
        System.out.println(String.format("牛逼logger记录:%s",message));
    }
}

第三,构建适配器类

这个类是适配器模式的核心,通过此类就可以将三方库提供的接口转换为系统的目标接口

public class LogAdapter implements LogFactory {
    private NbLogger nbLogger;

    public LogAdapter(NbLogger nbLogger) {
        this.nbLogger = nbLogger;
    }

    @Override
    public void debug(String tag, String message) {
        Objects.requireNonNull(nbLogger);
        nbLogger.d(1, message);
    }
}

LogAdapter实现了系统的目标接口,同时持有三方库NbLogger的引用。

第四,客户端使用

public class AdapterClient {
    public void recordLog() {
        LogFactory logFactory = new LogAdapter(new NbLoggerImp());
        logFactory.debug("Test", "我将使用牛逼logger打印log");
    }
}

可以看到,通过适配器客户端就可以很轻松的切换到新的日志系统了。

技术要点总结

  • 适配器LogAdapter 必须要实现目标接口,且依赖那个提供功能的类型,此处为NbLogger

优缺点

优点

  • 极大的增强了程序的可扩展性,通过此模式,你可以随意扩展程序的功能,但却不需要修改接口

缺点

  • 其实在我看来这个模式真没啥缺点,唯一可以称的上的缺点是多了一层,但是这也是没有办法的事情。

总结

设计模式值得你可以练习!

最后,如果你从本文中有所收获,可否点赞转发支持一下博主,你小小的鼓励,是激发博主持续写作的动力…

GitHub源码地址design-patterns

以上是关于秒懂设计模式之适配器模式(Adapter Pattern)的主要内容,如果未能解决你的问题,请参考以下文章

设计模式之十三:适配器模式(Adapter)

设计模式之Adapter(适配器)(转)

设计模式之结构型-适配器模式(Adapter)

设计模式之适配器模式 Adapter

设计模式之Adapter模式

设计模式之四:适配器模式(Adapter Pattern)