【C++设计模式】结构型模式:适配器模式

文章目录

结构型模式:适配器模式

适配器模式

适配器模式的动机确实是解决两个已有接口之间不兼容的问题,通过引入一个适配器类,将不兼容的接口进行转换,使它们能够协同工作,而无需修改已有的代码(通常是旧接口的代码),从而复用旧接口的功能,使其适应新接口的需求。

假设有一个旧的类 OldInterface,它提供了一个不兼容的接口,而现在有一个新的接口 NewInterface,我们希望将 OldInterface 适配为 NewInterface

cpp 复制代码
#include <iostream>

// 旧接口
class OldInterface {
public:
    virtual void oldRequest() {
        std::cout << "OldInterface: oldRequest\n";
    }
};

// 新接口
class NewInterface {
public:
    virtual void newRequest() {
        std::cout << "NewInterface: newRequest\n";
    }
};

// 适配器类,将 OldInterface 适配为 NewInterface
class Adapter : public NewInterface {
private:
    OldInterface* oldObj;

public:
    Adapter(OldInterface* obj) : oldObj(obj) {}

    void newRequest() override {
        // 在适配器中调用旧接口的方法,实现新接口的功能
        std::cout << "Adapter: calling oldRequest via newRequest\n";
        oldObj->oldRequest();
    }
};

// 客户端代码
int main() {
    OldInterface* oldObj = new OldInterface();
    NewInterface* adapter = new Adapter(oldObj);

    // 使用新接口调用适配器
    adapter->newRequest();

    delete oldObj;
    delete adapter;

    return 0;
}

旧接口 (OldInterface) 提供了一个方法 oldRequest(),这是系统中旧有的调用方式。而新接口 (NewInterface) 则要求使用方法 newRequest(),这是新系统中规定的调用方式。

由于 OldInterfaceNewInterface 的方法名和调用方式不同,直接在新系统中使用 OldInterface 的对象将导致编译错误或运行时错误,这就是所谓的不兼容的接口

为了复用旧接口的代码,我们可以通过适配器类 AdapternewRequest() 的调用转换为对 oldRequest() 的调用。这种方式不仅能够复用旧接口的功能,还能使新系统顺利运行。

应用实例

音频播放器

假设我们有一个音频播放系统,需要支持多种音频格式,但旧的播放器只支持MP3格式。我们可以使用适配器模式来扩展它以支持新的音频格式,如WAV。

cpp 复制代码
#include <iostream>
#include <string>

// 旧的音频播放器接口
class OldAudioPlayer {
public:
    void playMP3(const std::string& fileName) {
        std::cout << "Playing MP3 file: " << fileName << std::endl;
    }
};

// 新的音频播放器接口
class NewAudioPlayer {
public:
    virtual void play(const std::string& fileName) = 0;
};

// 适配器类
class AudioAdapter : public NewAudioPlayer {
private:
    OldAudioPlayer* oldPlayer;

public:
    AudioAdapter(OldAudioPlayer* player) : oldPlayer(player) {}

    void play(const std::string& fileName) override {
        // 假设所有非MP3文件格式都需要适配
        if (fileName.substr(fileName.size() - 4) == ".wav") {
            std::cout << "Adapter: Converting WAV file for playback.\n";
            // 适配的播放方式(实际情况下可能需要实现转换逻辑)
            std::cout << "Playing WAV file: " << fileName << std::endl;
        } else {
            // 直接使用旧播放器播放MP3
            oldPlayer->playMP3(fileName);
        }
    }
};


int main() {
    OldAudioPlayer* oldPlayer = new OldAudioPlayer();
    NewAudioPlayer* audioPlayer = new AudioAdapter(oldPlayer);

    audioPlayer->play("song.mp3");  // 使用旧播放器
    audioPlayer->play("track.wav");  // 使用适配器

    delete oldPlayer;
    delete audioPlayer;

    return 0;
}

日志记录系统

假设你有一个日志记录系统,旧的日志记录类只支持输出到控制台,而新的系统希望将日志记录到文件中。可以通过适配器来实现。

cpp 复制代码
#include <iostream>
#include <fstream>
#include <string>

// 旧的日志记录器
class ConsoleLogger {
public:
    void log(const std::string& message) {
        std::cout << "Log: " << message << std::endl;
    }
};

// 新的日志接口
class Logger {
public:
    virtual void log(const std::string& message) = 0;
};

// 适配器类
class FileLoggerAdapter : public Logger {
private:
    ConsoleLogger* consoleLogger;
    std::ofstream file;

public:
    FileLoggerAdapter(ConsoleLogger* logger) : consoleLogger(logger) {
        file.open("log.txt", std::ios::app);
    }

    void log(const std::string& message) override {
        consoleLogger->log(message); // 先输出到控制台
        file << "Log: " << message << std::endl; // 同时写入文件
    }

    ~FileLoggerAdapter() {
        file.close();
    }
};


int main() {
    ConsoleLogger* consoleLogger = new ConsoleLogger();
    Logger* logger = new FileLoggerAdapter(consoleLogger);

    logger->log("This is a log message."); // 同时输出到控制台和文件

    delete consoleLogger;
    delete logger;

    return 0;
}

电源适配器

假设你需要将220V电源转换为110V电源以供特定设备使用。可以使用适配器模式实现。

cpp 复制代码
#include <iostream>

// 旧的电源接口(220V)
class Power220V {
public:
    void providePower() {
        std::cout << "Providing power at 220V." << std::endl;
    }
};

// 新的电源接口(需要110V)
class Power110V {
public:
    virtual void providePower() = 0;
};

// 适配器类
class PowerAdapter : public Power110V {
private:
    Power220V* power220V;

public:
    PowerAdapter(Power220V* power) : power220V(power) {}

    void providePower() override {
        std::cout << "Adapter: Converting 220V to 110V." << std::endl;
        power220V->providePower(); // 调用旧的提供电源的方法
    }
};


int main() {
    Power220V* power220V = new Power220V();
    Power110V* power110V = new PowerAdapter(power220V);

    power110V->providePower(); // 提供110V电源

    delete power220V;
    delete power110V;

    return 0;
}
相关推荐
天若有情67331 分钟前
c++框架设计展示---提高开发效率!
java·c++·算法
Root_Smile1 小时前
【C++】类和对象
开发语言·c++
Reese_Cool1 小时前
【数据结构与算法】排序
java·c语言·开发语言·数据结构·c++·算法·排序算法
寒笙LED2 小时前
C++详细笔记(六)string库
开发语言·c++·笔记
就爱六点起4 小时前
C/C++ 中的类型转换方式
c语言·开发语言·c++
召木5 小时前
C++小白实习日记——Day 2 TSCNS怎么读取当前时间
c++·职场和发展
St_Ludwig5 小时前
C语言 蓝桥杯某例题解决方案(查找完数)
c语言·c++·后端·算法·游戏·蓝桥杯
Jack黄从零学c++5 小时前
opencv(c++)---自带的卷积运算filter2D以及应用
c++·人工智能·opencv
sweetheart7-75 小时前
LeetCode20. 有效的括号(2024冬季每日一题 11)
c++·算法·力扣··括号匹配
gma9996 小时前
brpc 与 Etcd 二次封装
数据库·c++·rpc·etcd