当前位置: 首页 > news >正文

设计模式:适配器模式(C++模式)

设计模式:适配器模式(C++模式)

文章目录

  • 设计模式:适配器模式(C++模式)
    • 1. 应用背景
    • 2. 代码

1. 应用背景

在最近面试的过程中,除了单例、工厂模式、观察者模式之外,其他的设计模式也经常涉及到了。因此记录一下,这是最原始的应用背景哈哈(开玩笑)。

适配器模式在生活中的应用也是很常见到的。比如我们电脑连接投影仪(或者显示屏)的时候,老一点的电脑接口经常是VGA的,而新一点的可以是HDMI的或者TypeC的。

假设我现在有一个老的电脑显示屏,只能接受VGA作为输入信号。而我的电脑比较新,只有HDMI的接口,也就是只能输出HDMI信号。那么这时候就需要一个转换器(适配器)来作为中间的桥梁,来将HDMI的信号转换为老的信号,从而被显示器接收工作。

在企业中,很多项目的接口经常是老的。这个老的一般指的是“接口传入的对象是老的”。而现在新开发了一些新的、好用的新对象,怎么把新的对象传入到老的接口里面?那就是使用适配器模式。

下面对适配器模式做一些抽象的总结:适配器类往往是继承自老的对象类,因此可以把适配器对象传入老的接口。而适配器类往往需要传入一个新的对象,在适配器的内部中完成的工作,都是新的对象完成的。这样从外界看起来,确实是对老接口传入了一个老对象(适配器),老对象又开放了一个接口接受新对象。当需要执行具体的任务时,是新的对象完成的。

2. 代码

按上面的场景,首先我们先考虑只有老接口和老对象的情况:

class VGA {
public:
	virtual void display() = 0; // 纯虚函数 统一接口
};

class Computer01 : public VGA {
public:
	void display() {
		cout << "play video by VGA!" << endl;
	}
};

class Projector {
public:
	void display(VGA* obj) { // 投影仪的接口比较老旧 只能接收VGA的信号作为播放源
		obj->display();
	}
};

int main() {
	Projector p;
	p.display(new Computer01());
	return 0;
}

这里的 Computer01 是第一代的电脑,比较老,只能输出VGA的信号,而投影仪只能接受一个VGA的老对象,这样工作是没问题的。

而问题是,假设有新的电脑版本 Computer02 出现了,只能输出HDMI信号,那么投影仪器是无法工作的:

class HDMI {
public:
	virtual void display() = 0; // 纯虚函数 统一接口
};


class Computer02 : public HDMI {
public:
	void display() {
		cout << "play video by HDMI!" << endl;
	}
};

所以现在需要创建一个适配器类VGAToHDMIAdaptor(属于旧对象类,继承自VGA):

class VGAToHDMIAdaptor : public VGA {
public:
	// 构造函数接收一个新的对象
	VGAToHDMIAdaptor(HDMI* obj) : obj_(obj) {}
	/*
		根据多态 虽然Projector对象中的 display函数接收到的是一个VGA的虚基类的指针 
		但是现在的VGAToHDMIAdaptor类是继承自VGA类,并进行重写
		因此最终调用到这个子类的display函数中
	*/
	void display() {
		obj_->display();
	}

private:
	HDMI* obj_;
};

VGAToHDMIAdaptor虽然是一个“旧对象”,但是它的构造函数可以接受一个新的对象。新的对象被使用了一根指针 obj_ 保存起来,等到需要真正做事的时候,就可以通过这根指针来完成。

这样,旧接口里面传入一个旧对象,这个旧对象又开放了一个接口(这里是构造函数)来接受一个新对象。因此,虽然有新对象(第二版的电脑)和旧接口(投影仪的输入 VGA信号),但是可以通过适配器来愉快的工作了:

int main() {

	Projector p;
	p.display(new VGAToHDMIAdaptor(new Computer02()));
	
	return 0;
}

全部代码:

#include <iostream>
using namespace std;

class VGA {
public:
	virtual void display() = 0; // 纯虚函数 统一接口
};

class Computer01 : public VGA {
public:
	void display() {
		cout << "play video by VGA!" << endl;
	}
};

class HDMI {
public:
	virtual void display() = 0; // 纯虚函数 统一接口
};


class Computer02 : public HDMI {
public:
	void display() {
		cout << "play video by HDMI!" << endl;
	}
};

class Projector {
public:
	void display(VGA* obj) { // 投影仪的接口比较老旧 只能接收VGA的信号作为播放源
		obj->display();
	}
};


class VGAToHDMIAdaptor : public VGA {
public:
	// 构造函数接收一个新的对象
	VGAToHDMIAdaptor(HDMI* obj) : obj_(obj) {}
	/*
		根据多态 虽然Projector对象中的 display函数接收到的是一个VGA的虚基类的指针 
		但是现在的VGAToHDMIAdaptor类是继承自VGA类,并进行重写
		因此最终调用到这个子类的display函数中
	*/
	void display() {
		obj_->display();
	}

private:
	HDMI* obj_;
};


int main() {

	Projector p;
	p.display(new Computer01());
	//p.display(new Computer02());

	p.display(new VGAToHDMIAdaptor(new Computer02()));
	
	return 0;
}

运行结果:

在这里插入图片描述

相关文章:

  • CGLIB 动态代理使用
  • Revit SDK:CreateFillPattern 创建填充样式
  • 当mybatisPlus与tk.mybatis遇到更新
  • sp.coo_matrix(), sp.eye()
  • linux虚拟机未建分区的情况下对磁盘进行扩容
  • 猿创征文|【数据结构】牛客网刷题
  • 【函数式编程】Java函数式编程学习
  • 基于springboot,vue旅游信息推荐系统
  • SSLError(MaxRetryError(‘HTTPSConnectionPool(host=\‘repo.anaconda.com\‘, port
  • vs生成dll且被java通过jna调用
  • DDD - 六边形架构和CQRS架构
  • 宠物寄养小程序实战教程02
  • 【计算机网络】运输层习题(谢希仁)(1)
  • 微信小程序抓包-夜神模拟器结合BurpSuite抓包(可用于现在最新版本微信)
  • SAR/毫米波雷达 论文阅读 | Freehand, Agile, and High-Resolution Imaging, IEEE Access 2019
  • [LeetCode] Wiggle Sort
  • 【399天】跃迁之路——程序员高效学习方法论探索系列(实验阶段156-2018.03.11)...
  • 【知识碎片】第三方登录弹窗效果
  • 07.Android之多媒体问题
  • Joomla 2.x, 3.x useful code cheatsheet
  • js 实现textarea输入字数提示
  • Laravel 中的一个后期静态绑定
  • MySQL Access denied for user 'root'@'localhost' 解决方法
  • vue中实现单选
  • 关键词挖掘技术哪家强(一)基于node.js技术开发一个关键字查询工具
  • 盘点那些不知名却常用的 Git 操作
  • 浅谈JavaScript的面向对象和它的封装、继承、多态
  • 区块链技术特点之去中心化特性
  • 容器服务kubernetes弹性伸缩高级用法
  • 融云开发漫谈:你是否了解Go语言并发编程的第一要义?
  • 使用iElevator.js模拟segmentfault的文章标题导航
  • 使用putty远程连接linux
  • 世界编程语言排行榜2008年06月(ActionScript 挺进20强)
  • 小程序测试方案初探
  • 一个SAP顾问在美国的这些年
  • nb
  • 【运维趟坑回忆录】vpc迁移 - 吃螃蟹之路
  • Spring Batch JSON 支持
  • 移动端高清、多屏适配方案
  • ​一些不规范的GTID使用场景
  • #{}和${}的区别?
  • #define MODIFY_REG(REG, CLEARMASK, SETMASK)
  • (01)ORB-SLAM2源码无死角解析-(56) 闭环线程→计算Sim3:理论推导(1)求解s,t
  • (11)工业界推荐系统-小红书推荐场景及内部实践【粗排三塔模型】
  • (Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息
  • (八)Spring源码解析:Spring MVC
  • (二)学习JVM —— 垃圾回收机制
  • (附源码)计算机毕业设计SSM智慧停车系统
  • (每日持续更新)jdk api之FileReader基础、应用、实战
  • (亲测)设​置​m​y​e​c​l​i​p​s​e​打​开​默​认​工​作​空​间...
  • (转)用.Net的File控件上传文件的解决方案
  • .NET Core跨平台微服务学习资源
  • .net mvc actionresult 返回字符串_.NET架构师知识普及
  • .Net小白的大学四年,内含面经
  • /boot 内存空间不够