【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;
}
相关推荐
Death20031 分钟前
PCL库中的算法封装详解
c++·qt·算法·3d
勇敢滴勇32 分钟前
【C++】继承和多态常见的面试问题
java·c++·面试
Qhumaing40 分钟前
小白C/C++语言常见问题(持续更新)
c语言·c++·算法
小柯J桑_1 小时前
C++:二叉搜索树(迭代)
c++·二叉搜索树
铭正1 小时前
c++时间形式转换
c++·时间格式转换
flying robot1 小时前
编程语言的设计模式
设计模式
啦啦啦!1 小时前
2024年10月30日(双指针算法)
c++·算法·leetcode
△曉風殘月〆2 小时前
C#与C++结构体的交互
c++·c#·p/invoke
hugerat2 小时前
嵌入式linux跨平台基于mongoose的TCP C++类的源码
linux·c++·tcp/ip
无敌岩雀2 小时前
C++设计模式创建型模式———单例模式
c++·单例模式·设计模式