适配器模式的三种C++实现

适配器模式(Adapter Pattern)是一种结构型设计模式,它允许接口不兼容的类能够一起工作。适配器模式通过将一个类的接口转换成客户希望的另外一个接口,解决了接口不兼容的问题。

适配器模式三种实现方式

1. 抽象接口方式(类适配器)

这种方式通过继承被适配类并实现目标接口来实现适配。

C++实现示例:

#include <iostream>
#include <string>

// 目标接口
class MediaPlayer {
public:
    virtual ~MediaPlayer() = default;
    virtual void play(const std::string& audioType, const std::string& fileName) = 0;
};

// 被适配的接口
class AdvancedMediaPlayer {
public:
    virtual ~AdvancedMediaPlayer() = default;
    virtual void playVlc(const std::string& fileName) = 0;
    virtual void playMp4(const std::string& fileName) = 0;
};

// 被适配的具体类
class VlcPlayer : public AdvancedMediaPlayer {
public:
    void playVlc(const std::string& fileName) override {
        std::cout << "Playing vlc file: " << fileName << std::endl;
    }
    
    void playMp4(const std::string& /*fileName*/) override {}
};

class Mp4Player : public AdvancedMediaPlayer {
public:
    void playVlc(const std::string& /*fileName*/) override {}
    
    void playMp4(const std::string& fileName) override {
        std::cout << "Playing mp4 file: " << fileName << std::endl;
    }
};

// 适配器
class MediaAdapter : public MediaPlayer {
private:
    AdvancedMediaPlayer* advancedMusicPlayer;
    
public:
    MediaAdapter(const std::string& audioType) {
        if (audioType == "vlc") {
            advancedMusicPlayer = new VlcPlayer();
        } else if (audioType == "mp4") {
            advancedMusicPlayer = new Mp4Player();
        } else {
            advancedMusicPlayer = nullptr;
        }
    }
    
    ~MediaAdapter() {
        delete advancedMusicPlayer;
    }
    
    void play(const std::string& audioType, const std::string& fileName) override {
        if (audioType == "vlc") {
            advancedMusicPlayer->playVlc(fileName);
        } else if (audioType == "mp4") {
            advancedMusicPlayer->playMp4(fileName);
        }
    }
};

// 客户端
class AudioPlayer : public MediaPlayer {
private:
    MediaAdapter* mediaAdapter;
    
public:
    ~AudioPlayer() {
        delete mediaAdapter;
    }
    
    void play(const std::string& audioType, const std::string& fileName) override {
        if (audioType == "mp3") {
            std::cout << "Playing mp3 file: " << fileName << std::endl;
        } else if (audioType == "vlc" || audioType == "mp4") {
            mediaAdapter = new MediaAdapter(audioType);
            mediaAdapter->play(audioType, fileName);
        } else {
            std::cout << "Invalid media type: " << audioType << std::endl;
        }
    }
};

// 使用示例
int main() {
    AudioPlayer audioPlayer;
    audioPlayer.play("mp3", "song.mp3");
    audioPlayer.play("vlc", "movie.vlc");
    audioPlayer.play("mp4", "video.mp4");
    audioPlayer.play("avi", "movie.avi");
    
    return 0;
}

2. 代理对象方式(对象适配器)

这种方式通过组合(持有被适配对象的引用)来实现适配。

C++实现示例:

#include <iostream>
#include <string>

// 目标接口
class CreditCard {
public:
    virtual ~CreditCard() = default;
    virtual void giveBankDetails() = 0;
    virtual std::string getCreditCard() = 0;
};

// 被适配的类
class BankDetails {
private:
    std::string bankName;
    std::string accHolderName;
    long accNumber;
    
public:
    void setBankName(const std::string& bankName) {
        this->bankName = bankName;
    }
    
    void setAccHolderName(const std::string& accHolderName) {
        this->accHolderName = accHolderName;
    }
    
    void setAccNumber(long accNumber) {
        this->accNumber = accNumber;
    }
    
    std::string getBankName() const {
        return bankName;
    }
    
    std::string getAccHolderName() const {
        return accHolderName;
    }
    
    long getAccNumber() const {
        return accNumber;
    }
};

// 适配器(代理对象)
class BankCustomer : public CreditCard {
private:
    BankDetails bankDetails;
    
public:
    void giveBankDetails() override {
        bankDetails.setAccHolderName("John Doe");
        bankDetails.setAccNumber(123456789);
        bankDetails.setBankName("ABC Bank");
    }
    
    std::string getCreditCard() override {
        return "Credit card issued for " + bankDetails.getAccHolderName() + 
               " from " + bankDetails.getBankName() + 
               " with account number " + std::to_string(bankDetails.getAccNumber());
    }
};

// 使用示例
int main() {
    CreditCard* targetInterface = new BankCustomer();
    targetInterface->giveBankDetails();
    std::cout << targetInterface->getCreditCard() << std::endl;
    
    delete targetInterface;
    return 0;
}

3. 参数化适配器方式

这种方式通过构造函数或方法参数传入被适配的对象,实现更灵活的适配。

C++实现示例:

#include <iostream>
#include <memory>

// 目标接口
class Temperature {
public:
    virtual ~Temperature() = default;
    virtual double getTemperature() const = 0;
};

// 被适配的类
class CelsiusThermometer {
private:
    double temperature;
    
public:
    explicit CelsiusThermometer(double temp) : temperature(temp) {}
    
    double getCelsiusTemperature() const {
        return temperature;
    }
};

// 适配器
class TemperatureAdapter : public Temperature {
private:
    std::shared_ptr<CelsiusThermometer> thermometer;
    bool toFahrenheit;
    
public:
    TemperatureAdapter(std::shared_ptr<CelsiusThermometer> thermo, bool toFahr)
        : thermometer(thermo), toFahrenheit(toFahr) {}
    
    double getTemperature() const override {
        if (toFahrenheit) {
            // 摄氏转华氏
            return (thermometer->getCelsiusTemperature() * 9.0 / 5.0) + 32.0;
        }
        return thermometer->getCelsiusTemperature();
    }
};

// 使用示例
int main() {
    auto celsiusThermometer = std::make_shared<CelsiusThermometer>(25.0);
    
    std::unique_ptr<Temperature> celsius = 
        std::make_unique<TemperatureAdapter>(celsiusThermometer, false);
    std::cout << "Temperature in Celsius: " << celsius->getTemperature() << std::endl;
    
    std::unique_ptr<Temperature> fahrenheit = 
        std::make_unique<TemperatureAdapter>(celsiusThermometer, true);
    std::cout << "Temperature in Fahrenheit: " << fahrenheit->getTemperature() << std::endl;
    
    return 0;
}

适配器模式的关键点
目标接口(Target): 客户端期望的接口

被适配者(Adaptee): 需要被适配的现有接口

适配器(Adapter): 将Adaptee接口转换为Target接口

三种实现方式的比较
方式    优点    缺点    适用场景
抽象接口(类适配器)    适配器可以重写被适配者的行为    需要多重继承(C++支持)    需要适配少量不兼容接口
代理对象(对象适配器)    更灵活,可以适配多个不同的被适配者    需要额外的间接层    需要适配多个不兼容接口
参数化适配器    最灵活,可以在运行时配置适配行为    接口可能变得复杂    需要运行时决定适配行为
实际应用场景
遗留系统集成:将新系统与旧系统集成时,可以使用适配器模式使旧系统的接口符合新系统的要求。

第三方库适配:当使用第三方库时,如果其接口不符合你的需求,可以使用适配器模式。

接口标准化:当有多个类实现相似功能但接口不同时,可以使用适配器模式提供统一的接口。

在C++中实现适配器模式时,需要注意资源管理(使用智能指针等RAII技术)和多线程安全性等问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值