2023-03-27
原文作者:ClarenceZero 原文地址:https://blog.csdn.net/ClarenceZero/article/details/106915912

适配器模式

定义

在计算机编程中,适配器模式(有时候也称包装样式或者包装)将一个类的接口适配成用户所期待的。一个适配允许通常因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。

适配器模式主要应用于,当接口里定义的方法无法满足客户的需求,或者说接口里定义的方法的名称或者方法界面与客户需求有冲突的情况。

(引用百度百科)

适配器模式 (英语:adapter pattern)有时候也称包装样式或者包装(wrapper)。将一个的接口转接成用户所期待的。一个适配使得因接口不兼容而不能在一起工作的类能在一起工作,做法是将类自己的接口包裹在一个已存在的类中。

适配器模式有两种实现方式: 类适配器对象适配器

  • 类适配器使用继承关系来实现
  • 对象适配器使用组合关系来实现。

(引用维基百科)

比如像USB 转接头充当适配器,把两种不兼容的接口,通过转接变得可以一起工作。

类图

  1. 类适配器

    202303272242151381.png

  2. 对象适配器

    202303272242156462.png

实现

类适配器

1. 被适配者

    public class Adaptee {
        /**
         * Info 级别
         * @param msg
         */
        public void slf4jInfo(String msg) {
            System.out.println("[Adaptee INFO]: " + msg);
        }
    
        /**
         * debug级别
         * @param msg
         */
        public void slf4jDebug(String msg) {
            System.out.println("[Adaptee DEBUG]: " + msg);
        }
    }

2. 适配器

    public interface Logger {
        /**
         * Info 级别
         * @param msg
         */
        void info(String msg);
    
        /**
         * debug级别
         * @param msg
         */
        void debug(String msg);
    }
     
    /**
     * 类适配器
     */
    public class Adaptor extends Adaptee implements Logger{
        @Override
        public void info(String msg) {
            slf4jInfo(msg);
        }
    
        @Override
        public void debug(String msg) {
            slf4jDebug(msg);
        }
    }

3. Main

    public class T {
        public static void main(String[] args) {
            Logger logger = new Adaptor();
            logger.info("hello");
        }
    }

对象适配器

1. 被适配者

    public class Adaptee {
        public void info(String msg) {
            System.out.println("[INFO]底层日志实现: Log4J2. " + msg);
        }
    
        public void debug(String msg) {
            System.out.println("[DEBUG]底层日志实现: Log4J2. " + msg);
        }
    }

2. 适配器

    /**
     * 定义日志接口
     */
    public interface Logger {
        /**
         * Info 级别
         * @param msg
         */
        void info(String msg);
    
        /**
         * debug级别
         * @param msg
         */
        void debug(String msg);
    }
    
    /**
     * 适配器持有被适配者的引用
     */
    public class LogAdaptor implements Logger{
        Adaptee log4J = new Adaptee();
        @Override
        public void info(String msg) {
            log4J.info(msg);
        }
    
        @Override
        public void debug(String msg) {
            log4J.debug(msg);
        }
    }

3. Main

    public class T {
        public static void main(String[] args) {
            Logger logger = new LogAdaptor();
            logger.info("hello");
        }
    }

总结

  1. 适配模式有两种,到底如何选择?

    判断的标准主要有两个,一个是Adaptee接口的个数,另一个是 AdapteeTarget 的契合程度。

    • 如果 Adaptee 接口并不多,那两种实现方式都可以。
    • 如果 Adaptee 接口很多,而且 Adaptee 和 Target 接口定义大部分都相同,那我们推荐使用类适配器,因为 Adaptor 复用父类 Adaptee 的接口,比起对象适配器的实现方式,Adaptor 的代码量要少一些。
    • 如果 Adaptee 接口很多,而且 Adaptee 和 Target 接口定义大部分都不相同,那我们推荐使用对象适配器,因为组合结构相对于继承更加灵活。
  2. 应用场景

    一般来说,适配器可看作为一种补偿模式,用来弥补设计上的缺陷。或者由于历史原因导致接口不统一,需要适配器适配两者不同接口。

    • 封装有缺陷的接口设计
    • 统一多个类的接口设计
    • 替换依赖的外部系统
    • 兼容老版本接口
    • 适配不同格式的数据
  3. 代理、桥接、装饰器、适配器 4 种设计模式的区别

    代理、桥接、装饰器、适配器,这 4 种模式是比较常用的结构型设计模式。它们的代码结构非常相似。笼统来说,它们都可以称为 Wrapper 模式,也就是通过 Wrapper 类二次封装原始类。

    • 代理模式:代理模式在不改变原始类接口的条件下,为原始类定义一个代理类,主要目的是控制访问,而非加强功能,这是它跟装饰器模式最大的不同。
    • 桥接模式:桥接模式的目的是将接口部分和实现部分分离,从而让它们可以较为容易、也相对独立地加以改变。
    • 装饰器模式:装饰者模式在不改变原始类接口的情况下,对原始类功能进行增强,并且支持多个装饰器的嵌套使用。
    • 适配器模式:适配器模式是一种事后的补救策略。适配器提供跟原始类不同的接口,而代理模式、装饰器模式提供的都是跟原始类相同的接口。

结语

内容引自有:

  • Head First 设计模式
  • 图解设计模式
  • Java设计模式之美(极客学院)
阅读全文