• Java设计模式之适配器模式(类结构型、对象结构型,双向适配器)


    1. 适配器模式

    注意:代理模式侧重访问控制功能(中介)。适配器模式侧重将适配者类转换成目标接口

    生活中经常出现两个对象因接口不兼容而不能一起工作的实例,这时需要第三者进行适配转换。例如讲中文的人同讲英文的人对话时需要一个翻译,用直流电的笔记本电脑接交流电源时需要一个电源适配器

    软件设计中也会出现当前系统与某个依赖组件之间接口不兼容,这时用适配器模式能很好地解决这些问题

    1.1 定义、优缺点、适用场景

    定义:适配器将一个类接口转换成另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。适配器模式分为类结构型模式和对象结构型模式两种,前者类之间的耦合度比后者高,所以应用相对较少些

    优点

    • 客户端通过适配器可以透明地调用目标接口
    • 可以直接复用现有的适配者类
    • 将目标接口和适配者类解耦,解决了目标接口和适配者类接口不一致的问题
    • 在很多业务场景中符合开闭原则

    缺点

    • 适配器编写过程需要结合业务场景全面考虑,可能会增加系统的复杂性
    • 增加代码阅读难度,降低代码可读性,过多使用适配器会使系统代码变得凌乱

    适用场景

    • 以前开发的系统存在满足新系统功能需求的类,但其接口同新系统的接口不一致
    • 使用第三方提供的组件,但组件接口定义和自己要求的接口定义不同

    1.2 模式的结构与实现(类结构型模式)

    结构

    • 目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口
    • 适配者(Adaptee)类:它是已经存在且提供功能的类,但由于接口不兼容,不能被客户端使用
    • 适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,这样客户就可以按目标接口的格式访问适配器

    实现
    描述:小明是中国人,只能听懂中国人说的话。有一天来了个只会说英语的英国朋友。所以找来了个翻译,翻译将英语翻译成中文,所以小明能听懂翻译这个中国人说的话

    public class AdapterTest {
    
        public static void main(String[] args) {
    
            // 翻译为了和小明说话,变成了中国人
            Chinese chinese = new Translater();
            XiaoMing xiaoMing = new XiaoMing();
            xiaoMing.hear(chinese);
    
        }
    }
    
    
    // 目标接口:中国人
    interface Chinese {
        // 说中文
        String speakChinese();
    }
    
    
    class XiaoMing {
        // 小明只能听中国人讲话
        public void hear(Chinese chinese) {
            String chineseWords = chinese.speakChinese();
            System.out.println("小明听懂了中国人说的:" + chineseWords);
        }
    }
    
    // 适配者类:真实的英国人
    class RealBritish {
        // 说了一句英语
        public String speakEnglish() {
            System.out.println("英国人说了句: hello");
            return "hello";
        }
    }
    
    // 适配器类:翻译---对接英国人,进行英语翻译。然后翻译为了和小明说话,变成了中国人
    class Translater extends RealBritish implements Chinese {
    
        // 翻译说中文
        @Override
        public String speakChinese() {
            String englishWords = speakEnglish();
            // 听英国人说的英语,然后转换成中文,再说出去
            System.out.println("翻译将英国人说的:hello,转换成中文:你好");
            return "你好";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    运行程序,结果如下:

    英国人说了句: hello
    翻译将英国人说的:hello,转换成中文:你好
    小明懂了中国人讲的:你好
    
    • 1
    • 2
    • 3

    1.3 对象结构型模式

    修改适配器类和客户端的代码即可,如下所示:

    public class AdapterTest {
    
        public static void main(String[] args) {
    
            // 翻译对接英国人。翻译为了和小明说话,变成了中国人
            Chinese chinese = new Translater(new RealBritish());
            XiaoMing xiaoMing = new XiaoMing();
            xiaoMing.hear(chinese);
    
        }
    }
    
    
    // 目标接口:中国人
    interface Chinese {
        // 说中文
        String speakChinese();
    }
    
    
    class XiaoMing {
        // 小明只能听中国人讲话
        public void hear(Chinese chinese) {
            String chineseWords = chinese.speakChinese();
            System.out.println("小明听懂了中国人说的:" + chineseWords);
        }
    }
    
    // 适配者类:真实的英国人
    class RealBritish {
        // 说了一句英语
        public String speakEnglish() {
            System.out.println("英国人说了句: hello");
            return "hello";
        }
    }
    
    // 适配器类:翻译---翻译为了和小明说话,变成了中国人
    class Translater implements Chinese {
        private RealBritish realBritish;
    
        // 对接英国人,进行英语翻译
        public Translater(RealBritish realBritish) {
            this.realBritish = realBritish;
        }
    
        // 翻译说中文
        @Override
        public String speakChinese() {
            String englishWords = this.realBritish.speakEnglish();
            // 听英国人说的英语,然后转换成中文,再说出去
            System.out.println("翻译将英国人说的:hello,转换成中文:你好");
            return "你好";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    运行程序,结构如下:

    英国人说了句: hello
    翻译将英国人说的:hello,转换成中文:你好
    小明听懂了中国人说的:你好
    
    • 1
    • 2
    • 3

    1.4 双向适配器模式

    双向适配器类要么把适配者接口转换成目标接口,要么把目标接口转换成适配者接口。不能同时对适配者接口和目标接口相互转换

    public class AdapterTest {
    
        public static void main(String[] args) {
    
            British british = new Translater(new RealChinese());
            Tom tom = new Tom();
            tom.hear(british);
            System.out.println("====昨天的一个翻译将中文翻译成英文。今天的另一个翻译将英文翻译成中文======");
            Chinese chinese = new Translater(new RealBritish());
            XiaoMing xiaoMing = new XiaoMing();
            xiaoMing.hear(chinese);
    
        }
    }
    
    // 英文翻译成中文的目标对象
    interface Chinese {
        String speakChinese();
    }
    
    // 中文翻译成英文的适配者类
    class RealChinese implements Chinese {
        @Override
        public String speakChinese() {
            System.out.println("中国人说了句: 你好");
            return "你好";
        }
    }
    
    
    class XiaoMing {
        public void hear(Chinese chinese) {
            String chineseWords = chinese.speakChinese();
            System.out.println("小明听懂了中国人说的:" + chineseWords);
        }
    }
    
    
    // 中文翻译成英文的目标对象
    interface British {
        String speakEnglish();
    }
    
    // 英文翻译成中文的适配者类
    class RealBritish implements British {
        @Override
        public String speakEnglish() {
            System.out.println("英国人说了句: hello");
            return "hello";
        }
    }
    
    
    class Tom {
        public void hear(British british) {
            String englishWords = british.speakEnglish();
            System.out.println("Tom听懂了英国人说的:" + englishWords);
        }
    }
    
    // 要么将中文翻译成英文;要么将英文翻译成中文。不能同时翻译中文和英文
    class Translater implements Chinese, British {
        private RealChinese realChinese;
        private RealBritish realBritish;
    
        public Translater(RealChinese realChinese) {
            this.realChinese = realChinese;
        }
    
        public Translater(RealBritish realBritish) {
            this.realBritish = realBritish;
        }
    
        @Override
        public String speakEnglish() {
            String chineseWords = this.realChinese.speakChinese();
            System.out.println("翻译将中国人说的:你好,转换成中文:hello");
            return "hello";
        }
    
        @Override
        public String speakChinese() {
            String englishWords = this.realBritish.speakEnglish();
            System.out.println("翻译将英国人说的:hello,转换成中文:你好");
            return "你好";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87

    运行程序,结果如下:

    中国人说了句: 你好
    翻译将中国人说的:你好,转换成中文:hello
    Tom听懂了英国人说的:hello
    ====昨天的一个翻译将中文翻译成英文。今天的另一个翻译将英文翻译成中文======
    英国人说了句: hello
    翻译将英国人说的:hello,转换成中文:你好
    小明听懂了中国人说的:你好
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • 相关阅读:
    Linux的进程管理
    31.3 Java进阶之lambda方法引用
    Mysql查看执行语句
    数据库内容快速回顾
    Python字典(dict)的操作方法汇总(约18种操作方法),并附示例代码
    MAUI与Blazor共享一套UI,媲美Flutter,实现Windows、macOS、Android、iOS、Web通用UI
    val的准确率高于train是过拟合吗
    【原创】MQTT开发笔记(三)Win10上部署Mosquitto
    总结:数组常用方法
    老弟手把手教你编译Spark3.2.1源码!!!!!
  • 原文地址:https://blog.csdn.net/yy8623977/article/details/125663934