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

news/2025/11/21 18:38:02/文章来源:https://www.cnblogs.com/tlnshuju/p/19254139

实用指南:【设计模式】适配器模式(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)可使任意两个不相关的类协作运行

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

(2)提升类的复用性

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

(3)增加类的透明性

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

(4)灵活性好

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

劣势:

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

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

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

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/972454.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

完整教程:【人工智能】神经网络的优化器optimizer(四):Adam自适应动量优化器

完整教程:【人工智能】神经网络的优化器optimizer(四):Adam自适应动量优化器pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-…

轻松速通:TTS播放、文件播放与录音的核心功能解析!

无论是开发语音助手、音频播放器,还是录音工具,TTS播放、文件播放与录音都是绕不开的核心功能。本文提炼核心流程,帮你跳过冗余细节,快速掌握这三大功能的核心实现逻辑。 一、概述 本文档详细介绍了基于 Air8000 开…

2025 中国法兰阀门十大品牌推荐:密封升级 + 场景适配,优质厂家护航流体系统安全

法兰阀门作为管道连接中的核心部件,凭借连接牢固、密封性能好的优势,广泛应用于石油化工、市政工程、能源电力、船舶制造等众多领域。2025 年,随着工业生产规模扩大与民生基建升级,市场对法兰阀门的密封可靠性、耐…

FPGA专用CLKUSR时钟引脚严重警告——Cyclone 10 GX

FPGA专用CLKUSR时钟引脚严重警告——Cyclone 10 GXCyclone 10 gx器件 使用Cyclone 10 gx器件时,由于把硬件给的管脚tcl脚本拉到工程里面了,编译后发现一个Critical Warning如下Critical Warning(18326): The design …

OPCUA探讨(五)——客户端代码解读:监控变量值与报警

本系列文章: OPCUA 探讨(一)——测试与开发环境搭建 OPCUA 探讨(二)——服务器节点初探 OPCUA 探讨(三)——客户端代码解读:基本配置与会话连接 OPCUA 探讨(四)——客户端代码解读:浏览服务器节点树 OPCUA …

2025 年度中国截止阀十大品牌推荐:绿色智造 + 特种工况突破,引领行业高质量发展

2025 年,随着 “双碳” 战略深入推进与高端制造业升级,截止阀作为流体系统的 “控制中枢”,其应用场景正加速向大口径、高压力、超低温、耐腐蚀等苛刻工况延伸,同时绿色智造、数字化运维与全生命周期质量管控成为行…

修改DTS适配遥控用户码

在将该DTS文件提交到Kernel后,若需适配遥控用户码,需修改 红外遥控(remote-controller)相关节点配置,具体对应DTS中的 pwm@ff420030 节点(RK3399常见红外遥控驱动节点),以下是具体修改位置及步骤: 一、定位需…

nginx性能优化之tcp调优

本文分享自天翼云开发者社区《nginx性能优化之tcp调优》.作者:江****禄 nginx在tcp连接上有2个如下配置:tcp_nodelay on , tcp_nopush off。这两个配置在tcp连接中的具体原理如何呢?在网络拥塞控制领域,我们知道有…

2025年11月安徽聚乙烯瓶、高阻隔瓶、聚酯瓶、农药瓶供应商排行榜:安徽金汇龙包装领跑行业

摘要 2025年农药包装行业迎来技术升级浪潮,随着环保政策收紧和智能制造的推进,农药瓶供应商面临新的机遇与挑战。本文基于市场调研数据和技术参数分析,为您呈现2025年11月农药瓶供应商综合排名,并提供详细对比表单…

2025年11月中国/安徽/聚乙烯瓶、高阻隔瓶、聚酯瓶、农药瓶厂家TOP10推荐:安徽金汇龙包装强势登顶

摘要 随着农药包装行业标准化进程加速,2025年聚乙烯瓶市场需求持续增长,行业技术门槛显著提升。本文基于生产工艺、质量控制、研发能力等维度,对全国聚乙烯瓶生产企业进行综合评估,为农药生产企业提供供应商选择参…

rich dataset 3D人体场景数据集

https://rich.is.tue.mpg.de/download.php

ICPC2025沈阳打铁日志

11.14坐飞机出发了,到沈阳挺晚了还尝了大油边。 11.15下午他们在打省赛,所以热身赛调到晚上了,午饭吃的餐票(味道一般,重点是菜的种类太少了,就十多个),衣服是绿马甲,我和y都不太合身,投壶好难,队长中5个,后…

UModel 数据治理:运维世界模型构建实践

阿里云推出 UModel 统一建模框架,将实体、关系、数据、知识、行动融为一体,为大模型提供可推理、可交互的运维世界模型,推动可观测从‘被动响应’迈向‘主动优化’的新阶段。作者:元乙 点击此处,观看视频解读! 从…

【springboot】 WebMvcConfigurer的使用

org.springframework.web.servlet.config.annotation.WebMvcConfigurer 的使用 一、基本概念 WebMvcConfigurer 接口提供了一组回调方法,用于配置 Spring MVC 的各种方面,如视图解析器、拦截器、跨域请求、消息转换器…

2025年11月21日

2025年11月21日class Solution { public:int singleNumber(vector<int>& nums) {int ans=0;for(int i:nums){ans=ans^i;}return ans;} };

实用指南:一文搞懂 DeepSeek API:兼容 OpenAI 接口的智能对话模型调用指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

形容词Test

1.Stamp-collecting can be enjoyed by the rich ad the poor alike. stamp n.邮票 can be enjoyed:can 情态动词,后接原型。is enjoyed 一般现在时的被动语态。alike:同样地(deepseek说alike在这里是副词,修饰by…

James Watsons

the high IQ happens when an East Asian but knows English. its just some B just knows 26 English.

2025年11月江苏/徐州vr设备、vr体验馆、5d影院、9d影院、拓普互动厂家推荐榜:拓普互动强势登顶

摘要 2025年9D影院行业迎来爆发式增长,技术革新和市场需求双重驱动下,品牌竞争日趋激烈。本文基于市场调研数据、技术参数对比和用户反馈,为您呈现2025年11月最具竞争力的9D影院品牌排行榜。本榜单旨在为投资者、采…

计算机网络:物理层 - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …