自学内容网 自学内容网

c++常见设计模式之适配器模式

基础介绍

适配器模式作为c++中常见的设计模式模式之一,是一种结构型设计模式。那适配器模式用于解决什么问题呢?答案是将一个类的接口转换成客户期待的另一个接口。适配器让原本不兼容不能一起工作的类可以协同工作。

典型原理

应该如何理解适配器模式呢?假设目前已经存在一个类,该类提供了某个功能A,现在由于需求的需要,需要新设计一个类,该类需要使用到已有类的功能A,但是新的需求与老的类提供的接口不一致,这种情况下就需要使用到适配器模式了。

实现适配器模式:继承+组合。通过这两种形式来实现适配器模式,涉及3个类:适配器类,新的接口类,已有的接口类。适配器类与新的接口类是继承关系;适配器类与已有的接口类是组合关系。具体的示例如下所示:

//新的支付接口
class ModernPayProcessor
{
    public:
        virtual void ProcessPay(double amount)=0;//纯虚函数 新的支付接口
        ....
}

//旧的支付接口
class oldPayProcessor
{
    public:
        //老的支付接口
        void processLegacyPayment(int amount, std::string currency) 
        {
            //具体的支付处理
        }

}

//适配器类
class Adaptor:public ModernPayProcessor
{
    private:
        oldPayProcessor* oldPaySystem;  //老的支付类
    public:
        Adaptor(oldPayProcessor* p):oldPaySystem(p);  //适配器类的构造函数
        void ProcessPay(double amount)  //必须实现这个纯虚函数,否则会编译报错
        {
            //转换数据类型,以实现旧的支付接口的调用
            int number = static_cast<int>(amout);
            oldPaySystem->processLegacyPayment(number, "USD");  //这个老接口与新接口相比,名称不一样,而且参数也不一样,非常典型。
        }
}

//使用实例
int main()
{
    oldPayProcessor old;  //旧的支付对象
    Adaptor adaptor(&old);  //新的适配器类
    
    adaptor.ProcessPay(13.14);
    return 0;
}

通过上面的例子可以很清楚的看明白适配器模式是如何实现的,以及适配器模式的含义。

适配器模式的多种应用

适配模式除了上面的实现方式,还有很多复杂的应用。

多接口适配

上面的例子是一个旧类的接口的适配,适配器模式还支持多个旧类的接口适配,如下例所示:

// 多个旧接口
class LegacyPrinter {
public:
    void printDocument(const std::string& doc) {
        std::cout << "Legacy Printer: " << doc << std::endl;
    }
};

class LegacyScanner {
public:
    std::string scanDocument() {
        return "Scanned content from legacy scanner";
    }
};

// 新的多功能设备接口
class ModernOfficeDevice {
public:
    virtual void print(const std::string& doc) = 0;
    virtual std::string scan() = 0;
    virtual ~ModernOfficeDevice() = default;
};

// 多功能适配器
class OfficeDeviceAdapter : public ModernOfficeDevice {
private:
    LegacyPrinter* printer;
    LegacyScanner* scanner;

public:
    OfficeDeviceAdapter(LegacyPrinter* p, LegacyScanner* s) 
        : printer(p), scanner(s) {}

    void print(const std::string& doc) override {
        printer->printDocument(doc);
    }

    std::string scan() override {
        return scanner->scanDocument();
    }
};

双向适配器

// 接口A
class InterfaceA {
public:
    virtual void operationA() = 0;
    virtual ~InterfaceA() = default;
};

// 接口B
class InterfaceB {
public:
    virtual void operationB() = 0;
    virtual ~InterfaceB() = default;
};

// 双向适配器
class BidirectionalAdapter : public InterfaceA, public InterfaceB {
private:
    InterfaceA* a;
    InterfaceB* b;

public:
    BidirectionalAdapter(InterfaceA* a_ptr, InterfaceB* b_ptr) 
        : a(a_ptr), b(b_ptr) {}

    // A -> B 适配
    void operationA() override {
        b->operationB();
    }

    // B -> A 适配
    void operationB() override {
        a->operationA();
    }
};

更加具体的例子:

#include <iostream>
#include <string>
#include <memory>

// 国内支付系统接口
class DomesticPayment {
public:
    virtual void payInCNY(double amount) = 0;
    virtual double getBalanceInCNY() = 0;
    virtual ~DomesticPayment() = default;
};

// 国际支付系统接口
class InternationalPayment {
public:
    virtual void payInUSD(double amount) = 0;
    virtual double getBalanceInUSD() = 0;
    virtual ~InternationalPayment() = default;
};

// 具体的国内支付实现
class AliPay : public DomesticPayment {
private:
    double balance = 1000.0;  // 初始余额

public:
    void payInCNY(double amount) override {
        std::cout << "使用支付宝支付 " << amount << " CNY" << std::endl;
        balance -= amount;
    }

    double getBalanceInCNY() override {
        return balance;
    }
};

// 具体的国际支付实现
class PayPal : public InternationalPayment {
private:
    double balance = 150.0;  // 初始余额

public:
    void payInUSD(double amount) override {
        std::cout << "Using PayPal to pay " << amount << " USD" << std::endl;
        balance -= amount;
    }

    double getBalanceInUSD() override {
        return balance;
    }
};

// 双向支付适配器
class PaymentAdapter : 
    public DomesticPayment, 
    public InternationalPayment {
private:
    std::shared_ptr<DomesticPayment> domesticPayment;
    std::shared_ptr<InternationalPayment> internationalPayment;
    const double USD_TO_CNY_RATE = 7.2;  // 汇率

public:
    PaymentAdapter(
        std::shared_ptr<DomesticPayment> domestic,
        std::shared_ptr<InternationalPayment> international
    ) : domesticPayment(domestic), 
        internationalPayment(international) {}

    // DomesticPayment 接口实现
    void payInCNY(double amount) override {
        std::cout << "适配器: 转换人民币支付请求" << std::endl;
        double usdAmount = amount / USD_TO_CNY_RATE;
        internationalPayment->payInUSD(usdAmount);
    }

    double getBalanceInCNY() override {
        double usdBalance = internationalPayment->getBalanceInUSD();
        return usdBalance * USD_TO_CNY_RATE;
    }

    // InternationalPayment 接口实现
    void payInUSD(double amount) override {
        std::cout << "Adapter: Converting USD payment request" << std::endl;
        double cnyAmount = amount * USD_TO_CNY_RATE;
        domesticPayment->payInCNY(cnyAmount);
    }

    double getBalanceInUSD() override {
        double cnyBalance = domesticPayment->getBalanceInCNY();
        return cnyBalance / USD_TO_CNY_RATE;
    }
};

// 客户端代码
void testPaymentSystems() {
    // 创建支付系统实例
    auto alipay = std::make_shared<AliPay>();
    auto paypal = std::make_shared<PayPal>();
    
    // 创建适配器
    PaymentAdapter adapter(alipay, paypal);
    
    std::cout << "\n=== 测试人民币支付接口 ===\n";
    adapter.payInCNY(100.0);
    std::cout << "人民币余额: " << adapter.getBalanceInCNY() << " CNY\n";
    
    std::cout << "\n=== Testing USD payment interface ===\n";
    adapter.payInUSD(20.0);
    std::cout << "USD balance: " << adapter.getBalanceInUSD() << " USD\n";
}

int main() {
    testPaymentSystems();
    return 0;
}

双向适配设计原则

// 保持接口清晰分离
class InterfaceA {
    virtual void methodA() = 0;
};

class InterfaceB {
    virtual void methodB() = 0;
};

class TwoWayAdapter : public InterfaceA, public InterfaceB {
    // 实现两个接口
};

class TwoWayAdapter {
private:
    // 封装转换逻辑
    void convertAToB() {
        // 转换逻辑
    }
    
    void convertBToA() {
        // 转换逻辑
    }
};


原文地址:https://blog.csdn.net/iqanchao/article/details/145261799

免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!