我所理解的设计模式(C++实现)——适配器模式(Adapter Pattern)

2023-11-01

解决的问题:

适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本接口不匹配而无法在一起工作的两个类能够在一起工作。比如说我的hp笔记本,美国产品,人家美国的电压是110V的,而我们中国的电压是220V,要在中国能使用,必须找个变压器转一下电压才可以。这个变压器就是个适配器。

适配器模式有类适配器和对象适配器两种模式,我们将分别讨论。


类适配器:

由图中可以看出,Adaptee类没有Request方法,而客户期待这个方法。为了使客户能够使用Adaptee类,提供一个中间环节,即类Adapter类,Adapter类实现了Target接口,并继承自AdapteeAdapter类的Request方法重新封装了AdapteeSpecificRequest方法,实现了适配的目的。

因为AdapterAdaptee是继承的关系,所以这决定了这个适配器模式是类的。

该适配器模式所涉及的角色包括:

目标(Target)角色:这是客户所期待的接口。因为C#不支持多继承,所以Target必须是接口,不可以是类。
源(Adaptee)角色:需要适配的类。
适配器(Adapter)角色:把源接口转换成目标接口。这一角色必须是类

    简单实现:

#include<iostream>
using namespace std;

// "ITarget"
class Target
{
public:
	// Methods
	virtual void Request(){};
};

// "Adaptee"
class Adaptee
{
public:
	// Methods
	void SpecificRequest()
	{
		cout<<"Called SpecificRequest()"<<endl;
	}
};

// "Adapter"
class Adapter : public Adaptee, public Target
{
public:
	// Implements ITarget interface
	void Request()
	{
		// Possibly do some data manipulation
		// and then call SpecificRequest  
		this->SpecificRequest();
	}
};


int main()
{
	// Create adapter and place a request
	Target *t = new Adapter();
	t->Request();

	return 0;
}

对象适配器:

从图中可以看出:客户端需要调用Request方法,而Adaptee没有该方法,为了使客户端能够使用Adaptee类,需要提供一个包装(Wrapper)类Adapter。这个包装类包装了一个Adaptee的实例,从而将客户端与Adaptee衔接起来。由于AdapterAdaptee是委派关系,这决定了这个适配器模式是对象的。

该适配器模式所涉及的角色包括:

目标(Target)角色:这是客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。
源(Adaptee)角色:需要适配的类。
适配器(Adapter)角色:通过在内部包装(Wrap)一个Adaptee对象,把源接口转换成目标接口。

简单实现:

#include<iostream>
using namespace std;

// "ITarget"
class Target
{
public:
	// Methods
	virtual void Request(){};
};

// "Adaptee"
class Adaptee
{
public:
	// Methods
	void SpecificRequest()
	{
		cout<<"Called SpecificRequest()"<<endl;
	}
};

// "Adapter"
class Adapter : public Target
{
private:
	Adaptee *adaptee;

public:
	Adapter()
	{
		adaptee = new Adaptee();
	}

	// Implements ITarget interface
	void Request()
	{
		// Possibly do some data manipulation
		// and then call SpecificRequest  
		adaptee->SpecificRequest();
	}
};


int main()
{
	// Create adapter and place a request
	Target *t = new Adapter();
	t->Request();

	return 0;
}

缺省适配器:

缺省适配器模式是一种特殊的适配器模式,但这个适配器是由一个抽象类实现的,并且在抽象类中要实现目标接口中所规定的所有方法,但很多方法的实现都是平庸的实现,也就是说,这些方法都是空方法。而具体的子类都要继承此抽象类。 

简单实现:

#include<iostream>
using namespace std;


class Target { 
public:
	virtual void f1(){}; 
	virtual void f2(){}; 
	virtual void f3(){};   
};

class DefaultAdapter : public Target 
{ 
public:
    void f1() { 
    } 

    void f2() { 
    } 

    void f3() { 
    } 
};

class MyInteresting :public DefaultAdapter
{ 
public:
     void f3(){       
		cout<<"呵呵,我就对f3()方法感兴趣,别的不管了!"<<endl;
    } 
};

int main()
{
	// Create adapter and place a request
	Target *t = new MyInteresting();
	t->f3();

	return 0;
}


实现要点:

1.Adapter模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况,在遗留代码复用、类库迁移等方面非常有用

2Adapter模式有对象适配器和类适配器两种形式的实现结构,但是类适配器采用多继承的实现方式,带来了不良的高耦合,所以一般不推荐使用。对象适配器采用对象组合的方式,更符合松耦合精神。

3Adapter模式的实现可以非常的灵活,不必拘泥于GOF23中定义的两种结构。例如,完全可以将Adapter模式中的现存对象作为新的接口方法参数,来达到适配的目的。

4Adapter模式本身要求我们尽可能地使用面向接口的编程风格,这样才能在后期很方便的适配


使用场景:

在以下各种情况下使用适配器模式:

1.系统需要使用现有的类,而此类的接口不符合系统的需要。

2.想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。这些源类不一定有很复杂的接口。

3.(对对象适配器而言)在设计里,需要改变多个已有子类的接口,如果使用类的适配器模式,就要针对每一个子类做一个适配器,而这不太实际。


LCL_data原创于CSDN.NET【http://blog.csdn.net/lcl_data/article/details/8780140


参考资料:

1.http://www.cnblogs.com/zhenyulu/articles/39386.html

2.http://www.cnblogs.com/Terrylee/archive/2006/02/18/333000.html


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我所理解的设计模式(C++实现)——适配器模式(Adapter Pattern) 的相关文章

  • C# 异步等待澄清?

    我读了here http blog stephencleary com 2012 02 async and await html that 等待检查等待的看看它是否有already完全的 如果 可等待已经完成 那么该方法将继续 运行 同步
  • 没有特殊字符的密码验证器

    我是 RegEx 的新手 已经进行了大量搜索 但没有找到任何具体内容 我正在编写一个验证密码字符串的正则表达式 可接受的字符串必须至少具有 4 种字符类型中的 3 种 数字 小写字母 大写字母 特殊字符 我对包含有一个想法 也就是说 如果这
  • std::vector 与 std::stack

    有什么区别std vector and std stack 显然 向量可以删除集合中的项目 尽管比列表慢得多 而堆栈被构建为仅后进先出的集合 然而 堆栈对于最终物品操作是否更快 它是链表还是动态重新分配的数组 我找不到关于堆栈的太多信息 但
  • 随着时间的推移,添加到 List 变得非常慢

    我正在解析一个大约有 1000 行的 html 表 我从一个字符串中添加 10 个字符串 td 每行到一个list td
  • 如何在 C++ 中标记字符串?

    Java有一个方便的分割方法 String str The quick brown fox String results str split 在 C 中是否有一种简单的方法可以做到这一点 The 增强分词器 http www boost o
  • 对类 static constexpr 结构的未定义引用,g++ 与 clang

    这是我的代码 a cp p struct int2 int x y struct Foo static constexpr int bar1 1 static constexpr int2 bar2 1 2 int foo1 return
  • 重载 (c)begin/(c)end

    我试图超载 c begin c end类的函数 以便能够调用 C 11 基于范围的 for 循环 它在大多数情况下都有效 但我无法理解和解决其中一个问题 for auto const point fProjectData gt getPoi
  • 如何获取 EF 中与组合(键/值)列表匹配的记录?

    我有一个数据库表 其中包含每个用户 年份组合的记录 如何使用 EF 和用户 ID 年份组合列表从数据库获取数据 组合示例 UserId Year 1 2015 1 2016 1 2018 12 2016 12 2019 3 2015 91
  • 两个静态变量同名(两个不同的文件),并在任何其他文件中 extern 其中一个

    在一个文件中将变量声明为 static 并在另一个文件中进行 extern 声明 我认为这会在链接时出现错误 因为 extern 变量不会在任何对象中看到 因为在其他文件中声明的变量带有限定符 static 但不知何故 链接器 瑞萨 没有显
  • WcfSvcHost 的跨域异常

    对于另一个跨域问题 我深表歉意 我一整天都在与这个问题作斗争 现在已经到了沸腾的地步 我有一个 Silverlight 应用程序项目 SLApp1 一个用于托管 Silverlight SLApp1 Web 的 Web 项目和 WCF 项目
  • 如何定义一个可结构化绑定的对象的概念?

    我想定义一个concept可以检测类型是否T can be 结构化绑定 or not template
  • 为什么 C# 2.0 之后没有 ISO 或 ECMA 标准化?

    我已经开始学习 C 并正在寻找标准规范 但发现大于 2 0 的 C 版本并未由 ISO 或 ECMA 标准化 或者是我从 Wikipedia 收集到的 这有什么原因吗 因为编写 审查 验证 发布 处理反馈 修订 重新发布等复杂的规范文档需要
  • 为什么使用小于 32 位的整数?

    我总是喜欢使用最小尺寸的变量 这样效果就很好 但是如果我使用短字节整数而不是整数 并且内存是 32 位字可寻址 这真的会给我带来好处吗 编译器是否会做一些事情来增强内存使用 对于局部变量 它可能没有多大意义 但是在具有数千甚至数百万项的结构
  • C 函数 time() 如何处理秒的小数部分?

    The time 函数将返回自 1970 年以来的秒数 我想知道它如何对返回的秒数进行舍入 例如 对于100 4s 它会返回100还是101 有明确的定义吗 ISO C标准没有说太多 它只说time 回报 该实现对当前日历时间的最佳近似 结
  • 在 WPF 中使用 ReactiveUI 提供长时间运行命令反馈的正确方法

    我有一个 C WPF NET 4 5 应用程序 用户将用它来打开某些文件 然后 应用程序将经历很多动作 读取文件 通过许多插件和解析器传递它 这些文件可能相当大 gt 100MB 因此这可能需要一段时间 我想让用户了解 UI 中发生的情况
  • 相当于Linux中的导入库

    在 Windows C 中 当您想要链接 DLL 时 您必须提供导入库 但是在 GNU 构建系统中 当您想要链接 so 文件 相当于 dll 时 您就不需要链接 为什么是这样 是否有等效的 Windows 导入库 注意 我不会谈论在 Win
  • 使用特定参数从 SQL 数据库填充组合框

    我在使用参数从 sql server 获取特定值时遇到问题 任何人都可以解释一下为什么它在 winfom 上工作但在 wpf 上不起作用以及我如何修复它 我的代码 private void UpdateItems COMBOBOX1 Ite
  • 为什么 std::uint32_t 与 uint32_t 不同?

    我对 C 有点陌生 我有一个编码作业 很多文件已经完成 但我注意到 VS2012 似乎有以下语句的问题 typedef std uint32 t identifier 不过 似乎将其更改为 typedef uint32 t identifi
  • 指针和内存范围

    我已经用 C 语言编程有一段时间了 但对 C 语言还是很陌生 有时我对 C 处理内存的方式感到困惑 考虑以下有效的 C 代码片段 const char string void where is this pointer variable l
  • 使用 WGL 创建现代 OpenGL 上下文?

    我正在尝试使用 Windows 函数创建 OpenGL 上下文 现代版本 基本上代码就是 创建窗口类 注册班级 创建一个窗口 choose PIXELFORMATDESCRIPTOR并设置它 创建旧版 OpenGL 上下文 使上下文成为当前

随机推荐

  • UE4 全局变量的应用(蓝图)

    4 20 1 创建全局变量 命名为MyGameInstance 2 创建一个变量 命名为MyB 3 在项目设置中 搜索GameInstence 并选中创建的全局变量 4 在蓝图里调用全局变量 5 成功打印
  • Tmux使用教程

    Tmux 是一款可以管理会话和分屏的终端复用器 在远程 SSH 断开后可以继续执行任务 重新连接后再继续会话 也能够将进程放到后台运行 需要时重新接管 为了防止 SSH 因网络断开造成的进程运行中断 推荐把所有需要长期运行的训练等任务都使用
  • 提升效率之如何打印出漂亮的带颜色的日志(输出高亮)

    花里胡哨的日志 1 花里胡哨的shell打印 2 c语言日志的彩色输出 日志系统对于一个软件的维护是很重要的 对于直接在本地打印的信息 可能包含非常多 如何才能快速发现自己想要打印的东西呢 带上颜色的输出 绝对是很好的选择 使用c c 的输
  • 二、网络编程之协议及协议格式详解

    引言 在网络编程中 我经常听人提起过协议 标准协议 协议族 TCP协议 传输层协议 诸如此类的协议概念 这些种类繁多的名词听着让人感觉头晕 所以今天继续学习和总结协议的相关知识 在前面一篇文章 网络编程之基础知识详解 中已经简单介绍过协议
  • vue3中使用echart多个图表,并且可以随着屏幕大小自适应布局

    一 在项目中安装echarts npm install echarts save 二 引入echarts 1 因为多个地方需要使用到这个echart图表 所以将这个echarts写在自定义组件中 子组件 chart vue div clas
  • Linux进程控制编程实验_02

    任务1 编写一个进程创建实验程序task51 c 创建如图所示的进程族亲结构 其中p1是程序启动时由加载程序创建第一个进程 各进程的输出信息分别如下 p1 I am father process p11 当前时间是 lt 年 月 日 时 分
  • Eclipse CDT c++支持C++11

    最近要在Linux 环境下面写一些代码 需要支持C 11 可是CDT 不认识C 11的特性 看了很多网上的配置资料 各种版本下面还是不一样 Eclipse 16 04 CDT 9 4 GCC 5 4 首先创建一个C project 写点C
  • mysql知识系列:用命令行远程登录Mysql

    参考 命令行登录Mysql 远程登录Mysql的方法 总结 mysql uxxx pxxx hxxx xxx xxx xxx P3306 xxx 为替换的内容
  • Python 基础合集8:类的继承和多态

    一 前言 本小节主要梳理类的继承和多态 继承包含三种形式 单继承 多层继承 多重继承 环境说明 Python 3 6 windows11 64位 二 继承 基础语法如下 class B A 表示的含义就是B 继承A A 是B 的父类 cla
  • 把数据插入到数据库的两种方法

    把表单中的数据插入到数据库中有两种方法 1 直接使用sql语句的 优点 速度快 不耗资源 缺点 不能传递太长的字段内容 字段比较多时不易排错 推荐有经验的编程者优先考虑 具体操作 假设表单中有以下字段 username password s
  • 阿里云免费试用服务器,怎么申请

    免费试用也要分个人用户和企业用户 个人用户选择比较少 目前只有下面这个配置 免费试用3个月 企业用户有4款机型 一 参与对象 满足以下全部条件的阿里云用户 1 阿里云注册会员用户 可以联系我注册账号 这样试用以后如果要新购也可以有优惠 2
  • 微信小程序调用天气信息

    在微信小程序中调用天气信息 下面是示例代码 wx request url example php 仅为示例 并非真实的接口地址 data x y header content type application json 默认值 succes
  • jdk和tomcat的关系

    1 什么是jvm 我们从操作系统的层面来理解 jvm其实就是操作系统中的一个进程 既然是一个进程 那么我们很容易的可以通过任务管理器来查看 假设此时我们启动myeclipse myeclipse其实就是用java语言编写的一个软件 他的运行
  • Java定时任务调度工具详解之Quartz篇(中级)一:浅谈JobExecutionContext&JobDatai&浅谈Trigger

    概要 OpenSymphony提供的强大的开源任务调度框架 官网 http www quartz scheduler org 纯java实现 精细控制排程 特点 强大的调度功能 灵活的应用方式 分布式和集群能力 主要用到的设计模式 Buil
  • 微信小程序+java后台+云服务器开发学习记录

    仅作为个人学习记录 1 使用了iview辅助开发 2 开发后台时 访问jsp和servlet突然404 检查以后发现8080端口被以前没清理干净的java程序占用了 到任务管理器里把java exe干掉以后重启idea一切恢复正常 困扰了我
  • 100流明相当于多少w_lx和瓦数换算(1lx等于多少w)

    你好 别想太多了 这个没得换算的所谓能换算的 都是已知光效的灯 就是每瓦多少流明的 然后再通过受照面积换算 希望对你有所帮助 望采纳 白炽灯的瓦数 光照强度 10W 65lm 15W 101lm 25W 198lm 40W 340lm 60
  • 身边那些百万年薪的程序员朋友

    大家好 我是寂小桦 争取每周在这里给大家分享自己作为独立开发者经历以及身边程序员朋友的趣事 百万年薪是个永远说不烂的话题 就在最近的一年 仿佛雨后春笋一般 身边开始涌现出很多年薪百万的程序员朋友 清一色集中在腾讯阿里京东头条这些公司 其中一
  • 数字电路的时钟(3)-- 抖动

    引言 抖动是时钟信号边沿事件的时间点集合相对于其理想值的离散时序变量 时钟信号中的抖动通常是由系统中的噪声或其他干扰导致的 具体因素包括热噪声 电源变化 负载条件 器件噪声以及相邻电路耦合的干扰等 抖动类型 时钟信号抖动定义有多种主要是 周
  • IDEA的Junit安装(添加jar包)

    1 安装junit插件 1 打开IDEA 点击文件 选择设置 setting 2 选择Plugins gt 点击Browse repositories 3 在搜索框中搜索Junit gt 找到Junit Generator V2 0点击 g
  • 我所理解的设计模式(C++实现)——适配器模式(Adapter Pattern)

    解决的问题 适配器模式把一个类的接口变换成客户端所期待的另一种接口 从而使原本接口不匹配而无法在一起工作的两个类能够在一起工作 比如说我的hp笔记本 美国产品 人家美国的电压是110V的 而我们中国的电压是220V 要在中国能使用 必须找个