基础介绍
适配器模式作为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() {// 转换逻辑}
};