C++设计模式之适配器模式:以家具生产为例

在家具生产车间里,我们经常会遇到这样的问题:新采购的配件(比如金属椅腿)接口与现有的生产框架(比如实木椅架)不匹配,直接安装会导致装配失败。这时候就需要一个"转换接头"来衔接两者------在设计模式中,这个"转换接头"就是适配器模式。本文将结合家具生产的实际场景,详解适配器模式的原理,并通过C++代码示例直观呈现其实现。

一、适配器模式核心概念

适配器模式(Adapter Pattern)是结构型设计模式的一种,核心作用是解决两个已有接口不兼容的问题,让原本因接口不匹配而无法协同工作的类能够正常交互。它就像家具生产中的"接口转换器",不改变原有类的功能和接口,而是通过新增一个适配类,将待适配类的接口转换为目标类期望的接口。

适配器模式包含三个核心角色,对应家具生产场景可如下映射:

  • 目标接口(Target):现有系统(或生产框架)期望的统一接口。比如家具厂生产实木椅时,椅架要求的"标准椅腿接口"(需包含"与椅架固定""承重检测"两个核心方法)。

  • 适配者(Adaptee):接口不兼容、但拥有核心功能的类。比如新采购的金属椅腿,它只有"金属部件固定""抗腐蚀检测"方法,无法直接对接椅架的标准接口。

  • 适配器(Adapter):连接目标接口和适配者的"转换类"。比如为金属椅腿定制的"金属椅腿适配器",它实现了标准椅腿接口,内部持有金属椅腿的实例,将标准接口的方法转换为金属椅腿能理解的调用。

二、家具生产场景:适配金属椅腿到实木椅架

2.1 场景需求

某家具厂原本只生产实木椅,椅架(客户端)仅支持对接"实木椅腿接口"(Target),该接口要求实现FixToFrame()(与椅架固定)和CheckLoad()(承重检测)两个方法。为降低成本,工厂新采购了一批金属椅腿(Adaptee),但金属椅腿仅提供MetalFix()(金属部件固定,需特殊螺丝)和CheckCorrosion()(抗腐蚀检测,金属椅腿核心检测项)方法,无法直接安装到现有椅架。需设计一个适配器,让金属椅腿能适配实木椅架的接口。

2.2 代码实现思路

  1. 定义目标接口(实木椅腿接口),包含椅架要求的两个核心方法;

  2. 实现适配者(金属椅腿类),包含其原有接口方法;

  3. 实现适配器(金属椅腿适配器),继承目标接口,内部聚合金属椅腿实例,在目标接口方法中调用金属椅腿的原有方法,并补充适配逻辑(如"将标准螺丝转换为金属椅腿所需的特殊螺丝");

  4. 客户端(椅架)通过目标接口调用,无需关注是实木椅腿还是适配后的金属椅腿。

2.3 完整代码示例

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;

// 1. 目标接口(Target):实木椅架期望的标准椅腿接口
class ISolidWoodChairLeg {
public:
    // 纯虚函数:与实木椅架固定(标准接口方法)
    virtual void FixToFrame() = 0;
    // 纯虚函数:承重检测(标准接口方法)
    virtual void CheckLoad() = 0;
    // 虚析构,确保子类析构正常
    virtual ~ISolidWoodChairLeg() {}
};

// 2. 适配者(Adaptee):新采购的金属椅腿(接口不兼容)
class MetalChairLeg {
public:
    // 金属椅腿原有方法:金属部件固定(需特殊螺丝)
    void MetalFix() {
        cout << "金属椅腿:使用M6特殊螺丝完成固定" << endl;
    }
    // 金属椅腿原有方法:抗腐蚀检测(金属核心检测项)
    void CheckCorrosion() {
        cout << "金属椅腿:通过盐雾测试,抗腐蚀等级达到500小时" << endl;
    }
};

// 3. 适配器(Adapter):金属椅腿适配器(实现目标接口,聚合适配者)
class MetalChairLegAdapter : public ISolidWoodChairLeg {
private:
    // 持有适配者(金属椅腿)的实例
    MetalChairLeg* m_metalLeg;
public:
    // 构造函数:传入金属椅腿实例
    MetalChairLegAdapter(MetalChairLeg* metalLeg) : m_metalLeg(metalLeg) {}
    
    // 实现目标接口方法1:与椅架固定(适配逻辑)
    void FixToFrame() override {
        cout << "适配器:将实木椅架的标准螺丝转换为金属椅腿所需的特殊螺丝" << endl;
        // 调用适配者的原有方法
        m_metalLeg->MetalFix();
        cout << "适配器:金属椅腿已适配并固定到实木椅架" << endl;
    }
    
    // 实现目标接口方法2:承重检测(适配逻辑)
    void CheckLoad() override {
        cout << "适配器:金属椅腿无需实木承重检测,替换为抗腐蚀检测" << endl;
        // 调用适配者的原有方法
        m_metalLeg->CheckCorrosion();
        cout << "适配器:金属椅腿检测通过,符合椅架要求" << endl;
    }
    
    // 析构函数:释放适配者(若由适配器管理则需释放,此处简化为外部管理)
    ~MetalChairLegAdapter() {
        // 若此处new了m_metalLeg,则需delete,此处为演示不做管理
    }
};

// 4. 具体目标类(ConcreteTarget):原有实木椅腿(符合标准接口)
class SolidWoodChairLeg : public ISolidWoodChairLeg {
public:
    void FixToFrame() override {
        cout << "实木椅腿:使用标准木螺丝固定到椅架" << endl;
    }
    void CheckLoad() override {
        cout << "实木椅腿:承重检测通过,可承受150kg重量" << endl;
    }
};

// 客户端(Client):家具厂的椅架装配流程
void AssembleChair(ISolidWoodChairLeg* chairLeg) {
    cout << "=== 开始椅架装配 ===" << endl;
    // 调用标准接口,无需关注是实木还是金属椅腿
    chairLeg->FixToFrame();
    chairLeg->CheckLoad();
    cout << "=== 椅架装配完成 ===" << endl << endl;
}

// 主函数:测试适配效果
int main() {
    // 场景1:使用原有实木椅腿装配
    ISolidWoodChairLeg* solidWoodLeg = new SolidWoodChairLeg();
    AssembleChair(solidWoodLeg);
    
    // 场景2:使用金属椅腿装配(通过适配器)
    MetalChairLeg* metalLeg = new MetalChairLeg();
    // 用适配器包装金属椅腿,转换为标准接口
    ISolidWoodChairLeg* adaptedMetalLeg = new MetalChairLegAdapter(metalLeg);
    AssembleChair(adaptedMetalLeg);
    
    // 释放资源
    delete solidWoodLeg;
    delete adaptedMetalLeg; // 适配器析构不管理metalLeg,需单独释放
    delete metalLeg;
    
    return 0;
}

三、代码运行结果与解析

  1. 适配器的转换作用MetalChairLegAdapter通过两个核心动作完成适配:① 继承目标接口,满足客户端调用要求;② 聚合适配者实例,将目标接口的方法(FixToFrameCheckLoad)转换为适配者的方法(MetalFixCheckCorrosion),并补充"螺丝转换""检测项替换"等适配逻辑。

四、适配器模式的适用场景总结

  • 新旧系统集成:如家具厂引入新配件(金属椅腿)到旧生产框架(实木椅架),接口不兼容时;

  • 统一接口规范:需为多个接口不同但功能相似的类(如金属椅腿、塑料椅腿)提供统一调用接口时。

相关推荐
CV_J1 天前
安装kibana
java·elasticsearch·spring cloud·docker·容器
码农水水1 天前
国家电网Java面试被问:TCP的BBR拥塞控制算法原理
java·开发语言·网络·分布式·面试·wpf
qq_336313931 天前
java基础-网络编程-TCP
java·网络·tcp/ip
咕噜咕噜啦啦1 天前
Java期末习题速通
java·开发语言
盐真卿1 天前
python2
java·前端·javascript
一嘴一个橘子1 天前
mybatis - 动态语句、批量注册mapper、分页插件
java
组合缺一1 天前
Json Dom 怎么玩转?
java·json·dom·snack4
危险、1 天前
一套提升 Spring Boot 项目的高并发、高可用能力的 Cursor 专用提示词
java·spring boot·提示词
kaico20181 天前
JDK11新特性
java
钊兵1 天前
java实现GeoJSON地理信息对经纬度点的匹配
java·开发语言