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)!