欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 维修 > 设计模式-adapter模式(适配器)

设计模式-adapter模式(适配器)

2025/2/28 4:24:11 来源:https://blog.csdn.net/u011942101/article/details/145808319  浏览:    关键词:设计模式-adapter模式(适配器)

解释

适配器模式(Adapter Pattern)用于将一个类的接口转换成客户端所期望的另一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。该模式属于结构型设计模式。

应用场景

场景1:旧系统与新系统的整合

当你有一个现有系统,并且想要集成一个第三方库或新的模块时,可能会遇到接口不匹配的问题。此时,适配器模式可以帮助你创建一个“桥梁”,使得旧代码能够调用新API,反之亦然。

场景2:不同第三方库之间的互操作性

在某些情况下,你可能需要同时使用多个来自不同供应商的库,但它们的API并不一致。适配器模式可以使这些库看起来具有相同的接口,从而简化了它们之间的交互。

场景3:遗留代码重构

当你对旧有的代码进行重构时,有时会发现一些类的设计不再符合当前的需求,或者引入了更好的实现方式。适配器模式可以用来逐步迁移系统,而不会立即废弃所有旧有逻辑。

不使用适配器模式的缺点

如果不使用适配器模式,在面对上述场景时,将会遇到以下问题:
代码重复:直接修改现有类以适应新需求会导致大量冗余代码。
耦合度高:紧密依赖特定实现,不利于维护和扩展。
难以维护:随着项目的发展,硬编码式的解决方案会变得越来越复杂难懂。
违反开闭原则:每当需要添加新的功能或支持新的接口时,都需要更改现有代码,而不是通过增加新的类来实现。

示例代码对比

1. 不使用适配器模式

假设我们有两个不同的图形绘制库 OldDrawingAPI 和 NewDrawingAPI,并且希望在同一个应用程序中使用它们。

// 旧版绘图API
class OldDrawingAPI {
public:void drawCircle(int x, int y, int radius) {// 实现...std::cout << "Using Old API to draw circle at (" << x << ", " << y << ") with radius " << radius << std::endl;}
};// 新版绘图API
class NewDrawingAPI {
public:void renderCircle(const Point& center, float radius) {// 实现...std::cout << "Using New API to render circle at (" << center.x << ", " << center.y << ") with radius " << radius << std::endl;}
};struct Point {int x, y;
};// 应用程序逻辑 - 直接调用不同API
void drawCirclesWithoutAdapter() {OldDrawingAPI oldApi;NewDrawingAPI newApi;// 使用旧API画圆oldApi.drawCircle(10, 20, 5);// 使用新API画圆Point p{15, 25};newApi.renderCircle(p, 7.5f);
}

缺点分析:

• 需要在应用层面上处理两种不同风格的API调用。
• 如果将来要替换其中一个API,则需要修改大量现有代码。
• 违反了单一职责原则,因为应用程序同时承担了业务逻辑和接口适配的责任。

2. 使用适配器模式

为了解决以上问题,我们可以为 OldDrawingAPI 创建一个适配器,使其能够像 NewDrawingAPI 一样被使用。

// 定义统一接口
class IDrawingAPI {
public:virtual void drawCircle(const Point& center, float radius) = 0;virtual ~IDrawingAPI() = default;
};// 新版绘图API适配器
class NewDrawingAPIAdapter : public IDrawingAPI {
private:NewDrawingAPI* api;
public:NewDrawingAPIAdapter(NewDrawingAPI* napi) : api(napi) {}void drawCircle(const Point& center, float radius) override {api->renderCircle(center, radius);}
};// 旧版绘图API适配器
class OldDrawingAPIAdapter : public IDrawingAPI {
private:OldDrawingAPI* api;
public:OldDrawingAPIAdapter(OldDrawingAPI* oapi) : api(oapi) {}void drawCircle(const Point& center, float radius) override {api->drawCircle(center.x, center.y, static_cast<int>(radius));}
};// 应用程序逻辑 - 统一调用接口
void drawCirclesWithAdapter() {OldDrawingAPI oldApi;NewDrawingAPI newApi;// 创建适配器实例IDrawingAPI* oldApiAdapter = new OldDrawingAPIAdapter(&oldApi);IDrawingAPI* newApiAdapter = new NewDrawingAPIAdapter(&newApi);// 现在可以统一调用了Point p{10, 20};oldApiAdapter->drawCircle(p, 5.0f);newApiAdapter->drawCircle({15, 25}, 7.5f);delete oldApiAdapter;delete newApiAdapter;
}// 使用智能指针改进资源管理
void drawCirclesWithAdapterSmartPtr() {OldDrawingAPI oldApi;NewDrawingAPI newApi;// 使用智能指针管理适配器生命周期std::unique_ptr<IDrawingAPI> oldApiAdapter(new OldDrawingAPIAdapter(&oldApi));std::unique_ptr<IDrawingAPI> newApiAdapter(new NewDrawingAPIAdapter(&newApi));// 统一调用Point p{10, 20};oldApiAdapter->drawCircle(p, 5.0f);newApiAdapter->drawCircle({15, 25}, 7.5f);
}

优点分析:

一致性:所有绘图操作都通过同一接口完成,提高了代码可读性和可维护性。
灵活性:新增加其他绘图库只需要编写对应的适配器即可,无需改动已有代码。
遵循开闭原则:当需要支持更多类型的绘图API时,只需扩展适配器,而不需要修改客户端代码。
降低耦合:将具体实现细节封装到适配器内部,减少了外部依赖关系。

总结

适配器模式不仅解决了接口兼容性的问题,还增强了系统的灵活性和可维护性。通过定义一个统一的接口,它可以隐藏底层实现的具体差异,使高层模块更加关注业务逻辑而非技术细节。此外,采用智能指针等现代C++特性还可以进一步提升资源管理和代码安全性。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词