尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

实用指南:【设计模式】适配器模式(Adapter)

实用指南:【设计模式】适配器模式(Adapter)
📅 发布时间:2026/6/19 4:40:20

实用指南:【设计模式】适配器模式(Adapter)

2025-11-21 18:33  tlnshuju  阅读(0)  评论(0)    收藏  举报

目录

一、问题导入

二、结构解析

1.示例问题

2.类适配器(Class Adapter)

3.对象适配器(Object Adapter)

4.默认适配器(Default Adapter)

5.结构成分

三、优劣


前言:大家可能会发现有些地方我会使用删除线,这并不是因为内容不重要。因为老师的课件并没有这样的拓展解释,而且其课件内容本身也并不一定完全正确,但是为了方便看课件复习的同学,就将课件以外的内容使用了删除线进行处理。此外,我个人认为老师的课件例子有些并不能完全体现对应设计模式的特点,所以会进行相应的修改。最后呢,对于只是为了应付课程的同学而言,代码部分可能并不是很重要,建议根据自身情况自行使用。有些地方如果存在错误,也希望大家能够指正,我会尽快修改。

Tips:对于这篇而言,三种适配器的实现方式老师并没有展开去讲

一、问题导入

在现实生活中,插座提供的是 220V 交流电,而手机充电需要的是 5V 左右的低压直流电,两者无法直接兼容。我们用的 “充电头” 会先把交流电转换成直流电,再把电压降到手机能接受的范围,最终实现安全充电。

这个帮不同设备 “搭桥” 的充电头,其实就是 “适配器” 的典型例子,而设计模式里的适配器模式解决的也是类似问题。

二、结构解析

1.示例问题

在游戏数值的设计当中,离不开一系列的配置信息。就比如经典的塔防游戏,防御塔的等级、攻击范围、攻击伤害等都是需要进行灵活的调整的,这些不能够在程序中写死,那么这些都将以文件格式给出。但是,策划可能提供给我们不同格式的文件,包含但不限于XML和JSON。那么作为程序的编写者,我们需要通过适配器模式,将这些不同格式的文件读入逻辑统一起来,让上层代码无需关心具体格式,只需调用统一的接口获取防御塔配置信息。

那么,我们接下来的核心目标就是定义一个统一的配置读取接口(ConfigReader),然后通过三种适配器模式,分别将XML读取器和JSON读取器适配到这个统一接口,使上层代码无需修改就能兼容不同格式。

这里有三种实现方式:
(1)类适配器(Class Adapter)

(2)对象适配器(Object Adapter)

(3)默认适配器(Default Adapter)

2.类适配器(Class Adapter)

通过多继承分别实现两个类适配器(XML 适配器和 JSON 适配器),都遵循FileReader接口

#pragma once
#include
namespace _ClassAdapterPattern
{//文件读取(目标接口)class FileReader{public:FileReader() = default;~FileReader() = default;virtual int get_tower_level()const = 0;virtual int get_hit_range()const = 0;virtual int get_attack_power()const = 0;};//XML解析器和JSON解析器(被适配者)class XMLParser{public:XMLParser() = default;~XMLParser() = default;int get_tower_level()const{ return 1; }int get_hit_range()const{ return 1; }int get_attack_power()const{ return 1; };};class JSONParser{public:JSONParser() = default;~JSONParser() = default;int get_tower_level()const{ return 2; }int get_hit_range()const{ return 2; }int get_attack_power()const{ return 2; };};//提供XML适配器和JSON适配器(适配器,通过类继承实现)class XMLAdapter:public FileReader,public XMLParser{public:XMLAdapter() = default;~XMLAdapter() = default;int get_tower_level()const override{ return XMLParser::get_tower_level(); }int get_hit_range()const override{ return XMLParser::get_hit_range(); }int get_attack_power()const override{ return XMLParser::get_attack_power(); }};class JSONAdapter:public FileReader,public JSONParser{public:JSONAdapter() = default;~JSONAdapter() = default;int get_tower_level()const override{ return JSONParser::get_tower_level(); }int get_hit_range()const override{ return JSONParser::get_hit_range(); }int get_attack_power()const override{ return JSONParser::get_attack_power(); }};void print_tower_config(FileReader* reader){std::cout << "防御塔等级:	" << reader->get_tower_level() << std::endl;std::cout << "攻击范围:	" << reader->get_hit_range() << std::endl;std::cout << "攻击伤害:	" << reader->get_attack_power() << std::endl;}void test(){FileReader*xml_reader = new XMLAdapter();FileReader*json_reader = new JSONAdapter();print_tower_config(xml_reader);print_tower_config(json_reader);}
}

3.对象适配器(Object Adapter)

通过 “实现接口 + 持有对象” 的方式,分别创建 XML 和 JSON 的对象适配器,共用FileReader接口。

#pragma once
#include
namespace _ObjectAdapterPattern
{//文件读取(目标接口)class FileReader{public:FileReader() = default;~FileReader() = default;virtual int get_tower_level()const = 0;virtual int get_hit_range()const = 0;virtual int get_attack_power()const = 0;};//XML解析器和JSON解析器(被适配者)class XMLParser{public:XMLParser() = default;~XMLParser() = default;int get_tower_level()const { return 1; }int get_hit_range()const { return 1; }int get_attack_power()const { return 1; };};class JSONParser{public:JSONParser() = default;~JSONParser() = default;int get_tower_level()const { return 2; }int get_hit_range()const { return 2; }int get_attack_power()const { return 2; };};//提供XML适配器和JSON适配器(适配器,通过包含对象实现)class XMLAdapter :public FileReader{private:XMLParser* xml_parser;public:XMLAdapter(XMLParser*parser){ xml_parser = parser;}~XMLAdapter() = default;int get_tower_level()const override { return xml_parser->get_tower_level(); }int get_hit_range()const override { return xml_parser->get_hit_range(); }int get_attack_power()const override { return xml_parser->get_attack_power(); }};class JSONAdapter :public FileReader{private:JSONParser* json_parser;public:JSONAdapter(JSONParser*parser){ json_parser = parser;}~JSONAdapter() = default;int get_tower_level()const override { return json_parser->get_tower_level(); }int get_hit_range()const override { return json_parser->get_hit_range(); }int get_attack_power()const override { return json_parser->get_attack_power(); }};void print_tower_config(FileReader* reader){std::cout << "防御塔等级:	" << reader->get_tower_level() << std::endl;std::cout << "攻击范围:	" << reader->get_hit_range() << std::endl;std::cout << "攻击伤害:	" << reader->get_attack_power() << std::endl;}void test(){XMLParser* xml_parser = new XMLParser();JSONParser* json_parser = new JSONParser();XMLAdapter* xml_adapter = new XMLAdapter(xml_parser);JSONAdapter* json_adapter = new JSONAdapter(json_parser);print_tower_config(xml_adapter);print_tower_config(json_adapter);}
}

4.默认适配器(Default Adapter)

当接口方法增多时,用默认适配器简化适配过程(当目标接口新增方法(如get_place_cost,XML 解析器因不支持该字段,无需修改适配器代码(直接复用默认适配器的 0 值),而 JSON 适配器只需重写新增方法即可)

#pragma once
#include
namespace _DefaultAdapterPattern
{//文件读取(目标接口)class FileReader{public:FileReader() = default;~FileReader() = default;virtual int get_tower_level()const = 0;virtual int get_hit_range()const = 0;virtual int get_attack_power()const = 0;virtual int get_place_cost()const = 0;};//默认适配器class DefaultAdapter :public FileReader{public:DefaultAdapter() = default;~DefaultAdapter() = default;int get_tower_level()const override { return 0; }int get_hit_range()const override { return 0; }int get_attack_power()const override { return 0; }int get_place_cost()const override { return 0; }};//XML解析器和JSON解析器(被适配者)class XMLParser{public:XMLParser() = default;~XMLParser() = default;int get_tower_level()const { return 1; }int get_hit_range()const { return 1; }int get_attack_power()const { return 1; };};class JSONParser{public:JSONParser() = default;~JSONParser() = default;int get_tower_level()const { return 2; }int get_hit_range()const { return 2; }int get_attack_power()const { return 2; };int get_place_cost()const { return 20; };};//提供XML适配器和JSON适配器(适配器,通过包含对象实现)class XMLAdapter :public DefaultAdapter{private:XMLParser* xml_parser;public:XMLAdapter(XMLParser* parser) { xml_parser = parser; }~XMLAdapter() = default;int get_tower_level()const override { return xml_parser->get_tower_level(); }int get_hit_range()const override { return xml_parser->get_hit_range(); }int get_attack_power()const override { return xml_parser->get_attack_power(); }};class JSONAdapter :public DefaultAdapter{private:JSONParser* json_parser;public:JSONAdapter(JSONParser* parser) { json_parser = parser; }~JSONAdapter() = default;int get_tower_level()const override { return json_parser->get_tower_level(); }int get_hit_range()const override { return json_parser->get_hit_range(); }int get_attack_power()const override { return json_parser->get_attack_power(); }int get_place_cost()const override { return json_parser->get_place_cost(); }};void print_tower_config(DefaultAdapter* reader){std::cout << "防御塔等级:	" << reader->get_tower_level() << std::endl;std::cout << "攻击范围:	" << reader->get_hit_range() << std::endl;std::cout << "攻击伤害:	" << reader->get_attack_power() << std::endl;std::cout << "放置费用:	" << reader->get_place_cost() << std::endl;}void test(){XMLParser* xml_parser = new XMLParser();XMLAdapter* xml_adapter = new XMLAdapter(xml_parser);print_tower_config(xml_adapter);JSONParser* json_parser = new JSONParser();JSONAdapter* json_adapter = new JSONAdapter(json_parser);print_tower_config(json_adapter);}
}

5.结构成分

可以很清楚的看到,适配器模式主要由三部分构成:

(1)目标接口:比如文件读取FileReader

(2)源接口:比如XMLParser和JSONParser

(3)适配器:比如XMLAdapter和JSONAdapter

三、优劣

优势:

(1)可使任意两个不相关的类协作运行

(适配器的核心价值就是通过转换接口,让原本因接口不兼容而无法协作的类(如XMLParser与FileReader)能够协同工作)

(2)提升类的复用性

(被适配者(如XMLParser)无需修改即可通过适配器复用在新场景中,避免重复开发。)

(3)增加类的透明性

(对上层代码屏蔽适配细节,即客户端只需关注目标接口(FileReader),无需知道底层是 XML 还是 JSON 解析,降低认知成本。)

(4)灵活性好

(更适用于对象适配器(通过组合可动态切换被适配者),类适配器因多继承耦合度高,灵活性稍弱。通过适配器隔离接口变化,降低系统修改成本。)

劣势:

(1)过度使用适配器会使系统变得非常混乱,难以从整体上把握

(过多的适配器会增加系统层级和理解成本,建议在接口设计初期规划统一标准,减少适配需求)

(2)最多只能适配一个适配者类,且目标类必须使抽象类

(此描述不准确,存在两点问题:

        ①适配器可以适配多个被适配者(如通过组合多个解析器对象实现复杂适配),并非 “最多一个”;

       ② 目标类可以是接口(如FileReader是纯虚类,即接口),而非必须是 “抽象类”(抽象类可包含非纯虚方法)。更合适的表述是:“类适配器受限于多继承特性(如 C++ 中),只能适配特定的被适配者类,灵活性低于对象适配器;且目标接口通常需要是纯虚类(接口)才能保证适配的统一性”。)

相关新闻

  • FPGA专用CLKUSR时钟引脚严重警告——Cyclone 10 GX
  • rich dataset 3D人体场景数据集
  • ICPC2025沈阳打铁日志

最新新闻

  • lidR架构解析与林业LiDAR数据处理高级应用
  • Vue3 为什么选择 Proxy?看完这篇彻底搞懂 JavaScript 代理模式
  • 云原生技术17-从Nginx到Envoy:为什么大厂都在迁移?xDS协议 + WASM扩展:Envoy高级玩法实战
  • HugeJsonViewer:打破GB级JSON文件查看的性能瓶颈
  • 2026年优秀的中粮长城葡萄酒潍坊总代理/中粮直营店长城葡萄酒潍坊总代理/原厂直供长城葡萄酒潍坊总代理选哪家靠谱 - 行业平台推荐
  • 3分钟解锁网易云音乐:免费音频解密转换全攻略

日新闻

  • 5分钟掌握Python进化算法:Geatpy高性能优化工具完全指南
  • Microchip 24AA044 EEPROM选型与应用全指南:从参数解析到实战编程
  • 华为的鸿蒙到底有多牛?为什么称作遥遥领先?

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号