• 设计模式之适配器模式


    1. 什么是适配器模式

    适配器模式(Adapter Pattern)是一种设计模式,用于将一个类的接口转换成客户端希望的另一个接口,使得原本由于接口不兼容而不能在一起工作的类可以一起工作。这种模式可以被认为是两个不兼容的接口之间的中间层。
    在这里插入图片描述

    • 适配器模式通常用于以下情况:

      系统已存在的类需要与其他不兼容的接口进行交互: 当你有一个现有类,但它的接口与你需要的接口不匹配时,可以使用适配器模式来解决这个问题。

      需要在系统中复用一些类,但其接口不符合系统的其他部分: 有时候你可能需要在一个系统中使用已存在的类,但其接口并不符合系统的其他部分,适配器模式可以让这些类可以在系统中共存。

    • 适配器模式通常涉及以下几个角色:

      目标接口(Target): 客户端期待的接口,适配器会实现这个接口。

      适配器(Adapter): 适配器是一个实现了目标接口并持有原始类实例的类。它充当连接目标接口和原始类的桥梁。

      被适配者(Adaptee): 需要被适配的已存在的类。它是适配器所要适配的对象。

    • 适配器模式可以分为两种类型:

      类适配器模式: 使用继承来实现适配器。适配器继承原始类,并实现目标接口。

      对象适配器模式: 使用组合来实现适配器。适配器持有原始类的实例,并实现目标接口。

    适配器模式使得原有类和新类可以协同工作,同时不破坏现有的设计。它提供了一种解耦的方式,允许新的功能与现有的功能无缝衔接,提供更好的可扩展性和灵活性。

    2. 适配器模式的应用

    2.1 场景一

    假设有一个老式音频播放器的类OldAudioPlayer,它有一个playOldFormat方法用于播放老式音频格式。现在有一个新的音频播放器接口NewAudioPlayer,其方法名为play用于播放新格式的音频文件。

    我们可以使用适配器模式来适配这两个接口,让OldAudioPlayer适配到NewAudioPlayer接口上。以下是Java代码示例:

    // 老式音频播放器类
    class OldAudioPlayer {
        public void playOldFormat() {
            System.out.println("Playing old audio format...");
        }
    }
    
    // 新式音频播放器接口
    interface NewAudioPlayer {
        void play();
    }
    
    // 适配器,将OldAudioPlayer适配为NewAudioPlayer接口
    class AudioPlayerAdapter extends OldAudioPlayer implements NewAudioPlayer {
        @Override
        public void play() {
            playOldFormat(); // 使用OldAudioPlayer的playOldFormat方法
        }
    }
    
    // 测试适配器模式
    public class Main {
        public static void main(String[] args) {
            // 使用适配器将OldAudioPlayer适配为NewAudioPlayer接口
            NewAudioPlayer newPlayer = new AudioPlayerAdapter();
    
            // 调用新的播放方法
            newPlayer.play();
        }
    }
    
    
    • 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

    在这个例子中,OldAudioPlayer是老式的音频播放器类,它的playOldFormat方法对应老式的播放功能。NewAudioPlayer是新式的音频播放器接口,有一个play方法对应新格式的播放功能。

    AudioPlayerAdapter是适配器类,它继承了OldAudioPlayer并实现了NewAudioPlayer接口。通过适配器,OldAudioPlayer的playOldFormat方法被转换成了符合NewAudioPlayer接口的play方法。

    在Main类的main方法中,创建了适配器对象,将其当做NewAudioPlayer接口来使用,最终调用了适配后的play方法,实际上执行了OldAudioPlayer的playOldFormat方法。

    2.2 场景二

    当你需要连接不同的数据库,比如MySQL和MongoDB,并希望使用统一的数据库操作接口时,适配器模式就非常有用。

    假设你有一个数据库操作的接口Database:

    // 数据库操作接口
    interface Database {
        void connect();
        void query(String query);
        void disconnect();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    现在,你有一个MySQL数据库连接器MySQLConnector,它实现了针对MySQL的连接、查询和断开连接的操作:

    // MySQL数据库连接器
    class MySQLConnector {
        public void connectMySQL() {
            System.out.println("Connecting to MySQL database...");
        }
    
        public void queryMySQL(String query) {
            System.out.println("Executing query in MySQL: " + query);
        }
    
        public void disconnectMySQL() {
            System.out.println("Disconnecting from MySQL database...");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    接下来,你有一个MongoDB数据库连接器MongoDBConnector,它也有对应的连接、查询和断开连接的操作:

    // MongoDB数据库连接器
    class MongoDBConnector {
        public void connectMongoDB() {
            System.out.println("Connecting to MongoDB...");
        }
    
        public void queryMongoDB(String query) {
            System.out.println("Executing query in MongoDB: " + query);
        }
    
        public void disconnectMongoDB() {
            System.out.println("Disconnecting from MongoDB...");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    现在,你可以创建一个适配器,将MySQL和MongoDB的连接器适配为统一的Database接口:

    // 适配器类
    class DatabaseAdapter implements Database {
        private MySQLConnector mysqlConnector;
        private MongoDBConnector mongoDBConnector;
    
        public DatabaseAdapter(MySQLConnector mysqlConnector) {
            this.mysqlConnector = mysqlConnector;
        }
    
        public DatabaseAdapter(MongoDBConnector mongoDBConnector) {
            this.mongoDBConnector = mongoDBConnector;
        }
    
        @Override
        public void connect() {
            if (mysqlConnector != null) {
                mysqlConnector.connectMySQL();
            } else if (mongoDBConnector != null) {
                mongoDBConnector.connectMongoDB();
            }
        }
    
        @Override
        public void query(String query) {
            if (mysqlConnector != null) {
                mysqlConnector.queryMySQL(query);
            } else if (mongoDBConnector != null) {
                mongoDBConnector.queryMongoDB(query);
            }
        }
    
        @Override
        public void disconnect() {
            if (mysqlConnector != null) {
                mysqlConnector.disconnectMySQL();
            } else if (mongoDBConnector != null) {
                mongoDBConnector.disconnectMongoDB();
            }
        }
    }
    
    
    • 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

    在这个例子中,DatabaseAdapter是一个适配器类,它将MySQL和MongoDB的不同接口适配为实现了相同的Database接口。这使得无论是MySQL连接器还是MongoDB连接器,都可以通过统一的Database接口来连接、查询和断开连接数据库。

    通过使用适配器模式,可以使得不同的数据库连接器拥有了相同的数据库操作接口,从而提供了一种更加统一和通用的数据库操作方式。

    3. 总结

    适配器模式是一种结构性设计模式,用于将一个类的接口转换成另一个接口,以便让不兼容的类能够一起工作。它通过创建一个适配器,使得原本由于接口不兼容而不能在一起工作的类可以进行交互。适配器模式涉及三个主要角色:目标接口定义了客户端期待的接口,被适配者是需要被适配的类,而适配器则实现了目标接口并持有被适配者的实例。适配器模式使得不同接口的类能够协同工作,提高了系统的灵活性和可扩展性,同时也允许已存在的类在新环境下得到复用。

  • 相关阅读:
    从0搭建新项目平台后台测试环境
    Spring Boot 整合邮件服务
    由SoftRefLRUPolicyMSPerMB=0引起的频繁Full GC问题排查实战
    卡尔曼滤波EKF
    3D打印机的使用教程( 超详细 )
    介绍下Java内存区域(运行时数据区)
    ZZ038 物联网应用与服务赛题第J套
    Linux网络-IP协议
    Oracle导出sequence
    算法基础-dfs的经验
  • 原文地址:https://blog.csdn.net/m0_54187478/article/details/134095848