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),并补充"螺丝转换""检测项替换"等适配逻辑。

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

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

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

相关推荐
曼巴UE52 小时前
UE5 C++ 动态多播
java·开发语言
VX:Fegn08952 小时前
计算机毕业设计|基于springboot + vue音乐管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·课程设计
程序员鱼皮3 小时前
刚刚,IDEA 免费版发布!终于不用破解了
java·程序员·jetbrains
Hui Baby3 小时前
Nacos容灾俩种方案对比
java
曲莫终3 小时前
Java单元测试框架Junit5用法一览
java
成富4 小时前
Chat Agent UI,类似 ChatGPT 的聊天界面,Spring AI 应用的测试工具
java·人工智能·spring·ui·chatgpt
凌波粒4 小时前
Springboot基础教程(9)--Swagger2
java·spring boot·后端
2301_800256114 小时前
【第九章知识点总结1】9.1 Motivation and use cases 9.2 Conceptual model
java·前端·数据库