C++之装饰器适配器模式

news2024/11/17 11:23:39

目录

一、装饰器模式

模式思想

模式简介

模式优点

模式缺点

代码实现

情景模拟

代码实现

运行结果

二、适配器模式

模式简介

介绍

优点

缺点

代码实现

情景模拟


一、装饰器模式

模式思想

模式简介

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。
这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

意图:

动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。
何时使用:
在不想增加很多子类的情况下扩展类。
如何解决:
将具体功能职责划分,同时继承装饰器模式

模式优点

装饰类被装饰类可以独立发展,不会相互耦合,装饰器模式是继承的一个替代模式,装饰器模式可以动态地扩展实现一个类的功能。

模式缺点

多层装饰比较复杂。

代码实现

情景模拟

我们还是拿汽车来举例子吧。
现在的汽车越来越智能化了,什么定速巡航自动刹车车道偏离等功能都逐渐进入我们的生活,为我们带来了更为便利的出行。

假设上述提到的定速巡航自动刹车车道偏离三个功能就是我们想要为汽车装饰的功能,汽车默认的功能配置有:基本配置

得到具体的汽车(宝马奥迪奔驰)后,我们可以选择性地增加装饰功能。

代码实现

具体实现如下:


//抽象基类
class Car
{
public:
	virtual void show() = 0;
};

//三个实体的基类
class Bmw : public Car
{
public:
	void show()
	{
		cout << "这是一辆宝马汽车,配置有:基本配置";
	}
};
class Audi : public Car
{
public:
	void show()
	{
		cout << "这是一辆奥迪汽车,配置有:基本配置";
	}
};
class Benz : public Car
{
public:
	void show()
	{
		cout << "这是一辆奔驰汽车,配置有:基本配置";
	}
};

//装饰器的基类
class CarDecorator : public Car
{
public:
	CarDecorator(Car* p):pCar(p)
	{}
private:
	Car* pCar;
};

//装饰器1 :定速巡航
class ConcreateDecorator1 : public Car
{
public:
	ConcreateDecorator1(Car* p):pCar(p)
	{}
	void show()
	{
		pCar->show();
		cout << "定速巡航功能,";
	}
private:
	Car* pCar;
};
//装饰器2 :自动刹车
class ConcreateDecorator2 : public Car
{
public:
	ConcreateDecorator2(Car* p) :pCar(p)
	{}
	void show()
	{
		pCar->show();
		cout << "自动刹车";
	}
private:
	Car* pCar;
};
//装饰器3 :车道偏离
class ConcreateDecorator3 : public Car
{
public:
	ConcreateDecorator3(Car* p) :pCar(p)
	{}
	void show()
	{
		pCar->show();
		cout << "车道偏离";
	}
private:
	Car* pCar;
};

运行结果

接着我们可以使用如下代码:

void main()
{
	Car* p1 = new ConcreateDecorator1(new Bmw());
	p1 = new ConcreateDecorator2(p1);
	p1->show();
	cout << endl;

	Car* p2 = new ConcreateDecorator2(new Audi());
	p2->show();
	cout << endl;

	Car* p3 = new ConcreateDecorator3(new Benz());
	p3->show();
	cout << endl;
}

可以看到,我们在运行代码中:
宝马汽车增加了Decorator01(定速巡航)Decorator02(自动刹车)Decorator03(车道偏离)的配置;
奥迪汽车增加了Decorator02(自动刹车配置;
奔驰汽车增加了Decorator03(车道偏离)配置。

二、适配器模式

模式简介

介绍

适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。

这种类型的设计模式属于结构型模式

意图:
将一个类的接口转换成为客户希望的另一个接口
适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
主要解决:
主要解决在软件系统中,常常要将一些“现存的对象”放到新环境中,而新环境的接口是现有对象不能满足的。

优点

  1. 可以让任何两个没有关联的类一起工作;
  2. 提高了类的复用;
  3. 增加了类的透明度;
  4. 灵活性好。

缺点

过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。

代码实现

情景模拟

同样的,我们来模拟这么一个场景:

我们要安装一个投影仪:能够将电脑上的画面投影出来,对于投影仪来说,常见的接口有:VGA、HTMI接口,但是对于不同的电脑,接口一定是固定的,一个电脑必然只有一种接口,我们往往会出现接口不适配的情况。

我们就来模拟不兼容的两个接口:VGAHDMI之间,如何通过一个适配器adapter连接在一起工作的。

当我们的电脑是VGA接口的时候,我们很自然能连接VGA的投影仪,但是当我们想要去连接HTMI的投影仪时,问题必然就出现了。

 我们可以添加一个适配器类:

/*
适配器模式:让不兼容的接口可以在一起工作

VGA接口的电脑,投影仪也是VGA接口
*/

//VGA接口类
class VGA
{
public:
	virtual void play() = 0;
};

//表示支持VGA接口的投影仪
class TV1 :public VGA
{
public:
	void play()
	{
		cout << "通过VGA接口连接投影仪,进行视频播放 " << endl;
	}
};

//实现一个电脑类(只支持VGA接口)
class Computer
{
public:
	//由于电脑支持VGA接口,所以该方法的参数智能支持VGA即可的指针/引用
	void playVideo(VGA* pVGA)
	{
		pVGA->play();
	}
};
/*
方法1:换一个支持HDMI接口的电脑,这个就叫代码重构
方法2:买一个转换头(适配器),能够把VGA信号转换成?HDMI信号,这个叫添加适配器类

*/

//进了一批新的投影仪,但是新的投影仪都是只支持HDMI接口
//HDMI接口类
class HDMI
{
public:
	virtual void play() = 0;
};
//表示支持HDMI接口的投影仪
class TV2 :public HDMI
{
public:
	void play()
	{
		cout << "通过HTMI接口连接投影仪,进行视频播放 " << endl;
	}
};

//由于电脑(VGA接口)和投影仪(HTMI接口)无法直接相连,所以需要添加适配器类
class VGATOHDMI :public VGA
{
public:
	VGATOHDMI(HDMI* p) :pHdmi(p)
	{
	}
	void play()//该方法相当于就是转换头,做不同接口的信号转换
	{
		pHdmi->play();
	}
private:
	HDMI* pHdmi;
};

运行一下:

void main()
{
	Computer cc;
	cc.playVideo(new TV1());
	
	cc.playVideo(new VGATOHDMI(new TV2()));
	
}

结果:

 

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

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

相关文章

前端基础(三十六):读取本地音视频设备并进行播放

效果 navigator.mediaDevices.enumerateDevices 请求媒体输入和输出设备的列表&#xff0c;例如麦克风&#xff0c;摄像机&#xff0c;耳机设备等 navigator.mediaDevices.getUserMedia 会提示用户给予使用媒体输入的许可&#xff0c;媒体输入会产生一个MediaStream&#xff0c…

伺服系统行业发展

伺服系统行业发展 1 介绍1.1 概述1.2 一般应用1.3 分类按系统功率分类按动力来源分类 1.4 工业控制中的伺服系统1.5 数字信号驱动与模拟信号驱动对比1.6 发展历史 2 伺服系统厂家工业机械臂移动AMR 3 关键指标及难点4 三相交流逆变器&#xff08;直流电转换为交流电&#xff09…

创建 Code Interpreter Demo: 一次实践的探索

好消息&#xff0c;好消息&#xff0c;Code Interpreter可以测试使用了&#xff01;&#xff01;&#xff01; 在这篇文章中&#xff0c;我们将探索如何创建一个 Code Interpreter Demo。提交一个2023年1-5月份的融资记录数据&#xff0c;让它来帮我们分析一下这些数据。 执行…

TCP 重传机制 滑动窗口 流量控制 拥塞控制 学习总结!

大家好&#xff0c;我是三叔&#xff0c;很高兴这期又和大家见面了&#xff0c;一个奋斗在互联网的打工人。 这篇博客主要记录 tcp 的基础知识的学习总结相关内容&#xff01;备注&#xff1a;图片均来自作者&#xff1a;小林哥 tcp 的三大特性 tcp 大家都不陌生&#xff0c…

Python制作gif表情包生成工具,斗图再也不会输啦

在当前无表情包不会聊天的时代&#xff0c;怎么也不能输在表情包数量不足上啊&#xff0c;今天咱们就来制作一个 gif 生成工具&#xff0c;用来制作表情包也太好用啦 先来看看整体效果 技术交流 技术要学会分享、交流&#xff0c;不建议闭门造车。一个人可以走的很快、一堆人…

如何解决PostgreSQL执行语句长时间卡着不动,不报错也不执行的问题?

1 问题现象 执行SQL语句&#xff0c;卡着不动&#xff0c;不成功也不执行&#xff0c;就像挂住了一样。 truncate table simple; 2 原因分析 一般来说&#xff0c;语句呈现卡着的状态&#xff0c;主要会是两种原因比较多&#xff0c; 原因1&#xff1a;SQL语句是一个耗时操…

Java8新特性——lambda表达式、函数式接口、方法引用、Stream API与Optional类

目录 一、lambda表达式 (一)lambda相关概念 (二)lambda示例 (三)lambda用法 1.语法格式一&#xff1a;无参&#xff0c;无返回值 2.语法格式二&#xff1a;有参数&#xff0c;无返回值 3.数据类型可以省略&#xff0c;因为可由编译器推断得出&#xff0c;称为”类型推断…

统计数据记录

分红20% 分红22% 分红25%

手把手教大家实现 npm 包,并发布 npm 仓库,搭建文档(二)

昨天写了第一篇文章,反响平平 一个 NPM 包,帮助数十万程序员提高数十倍效率,难道不开源出来?(一) 首先贴下我们的官网 【预览页】 https://kennana.github.io/toolkit-use/ 我们的推特 【toolkituse】 https://twitter.com/Toolkituse 我们的github 【toolkit-u…

实现一个周选择器组件

1、需求&#xff1a; 默认每个月的第一个周一为该月的第一周开始&#xff0c;规则如图所示 2、使用到的工具&#xff1a; vue2vant2momentjs 3、父组件&#xff1a; data中定义涉及到的参数 minDate: new Date(this.$moment().subtract(12,month)) maxDate: new Date(),…

OpenCV 入门教程:全局阈值处理

OpenCV 入门教程&#xff1a;全局阈值处理 导语一、全局阈值处理二、示例应用2.1 图像二值化2.2 图像去噪 总结 导语 全局阈值处理是图像处理中常用的技术之一&#xff0c;用于将图像转换为二值图像&#xff0c;从而提取感兴趣的目标区域。在 OpenCV 中&#xff0c;全局阈值处…

Mathtype公式编号,章节号修改

正常插入公式时&#xff0c;选择有编号没有任何问题&#xff0c;但是&#xff0c;当需要根据章节编号时&#xff0c;这个如何处理呢&#xff0c;这个时候需要 公式编号-章节-修改分隔符&#xff0c;然后会弹出一个对话框&#xff0c;这时可以修改章节开始序号。 此外&#xff…

【力扣周赛】第 353 场周赛

文章目录 Q1&#xff1a;6451. 找出最大的可达成数字&#xff08;脑筋急转弯&#xff1f;&#xff09;思路竞赛时代码 Q2&#xff1a;6899. 达到末尾下标所需的最大跳跃次数&#xff08;DP&#xff09;思路竞赛时代码 Q3&#xff1a;6912. 构造最长非递减子数组&#xff08;DP&…

Openssh升级方法

文章目录 Openssh升级方法一.安装openssh模拟未升级版本二.查看当前的ssh服务版本 三.启动telnet、安装rzsz工具、创建普通账号&#xff0c;防止因为卸载openssh而导致无法登录主机四.卸载openssh的rpm安装包&#xff08;备注&#xff1a;此处未卸载ssl安装包&#xff09;&…

【WebGIS初学到入职】(15)入职一年的总结与分享

题外话 看看大纲可以怎么写&#xff0c;问问ChatGPT&#xff1a; ……算了&#xff0c;还是随便写写吧。 所以时间过得也是有够快的&#xff0c;这就一年了。 平淡 入职一年&#xff0c;已经看到好些位女同事结婚了&#xff08;男同事一个没有&#xff09;。领导和同事都挺…

汽车网站建设:开启汽车行业数字化转型的大门

随着科技的进步和互联网的普及&#xff0c;越来越多的汽车企业开始意识到一个强大的在线存在的重要性。汽车网站的兴起为汽车行业带来了新的机遇和好处。本文将简要介绍什么是汽车网站&#xff0c;探讨汽车网站的好处&#xff0c;并提供一些快速制作搭建汽车网站的方法。 汽车网…

@JsonFormat(pattern = “yyyy-MM-dd“, timezone = “GMT+8“) 日期格式

前端去掉时分秒 &#xff1a; /*** 出生日期*/ JsonFormat(pattern "yyyy-MM-dd", timezone "GMT8")// 解决后端到前端显示问题 DateTimeFormat(pattern "yyyy-MM-dd")// 解决前端到后端保存问题 TableField(value "birthday") A…

Django_静态资源配置和ajax(九)

目录 一、静态资源配置 二、AJAX ajax作用 使用ajax 1、环境配置 2、创建html模板文件 3、编写视图函数并添加路由 4、运行django开发服务器进行验证 源码等资料获取方法 一、静态资源配置 静态资源的相关配置都在项目目录下的 settings.py 文件中进行配置。配置参数如…

架构训练营笔记系列: 模块 1-2课

郭东白老师的架构课偏理论&#xff0c;属于道层级。李云华老师的课偏实践&#xff0c;属于术层级。没有理论不会举一反三&#xff0c;只有理论&#xff0c;就是纸上谈兵&#xff0c;两个课都很好。 架构与程序思维的区别 程序 逻辑实现 架构 判断 取舍 架构设计的关键不只…

ansible 报错 DEPRECATION WARNING 解决

报错信息 [DEPRECATION WARNING]: Distribution Ubuntu 18.04 on host 192.168.1.1 should use /usr/bin/python3, but is using /usr/bin/python for backward compatibility with prior Ansible releases. A future Ansible release will default to using the discovered …