C++设计模式-- 2.代理模式 和 外观模式

文章目录

  • 代理模式
  • 外观模式
    • 角色和职责
    • 代码演示一:
    • 代码演示二:
    • 外观模式适用场景

代理模式

代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合 或不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

代理模式有以下三种角色:
Subject(抽象主题角色):真实主题与代理主题的共同接口。
RealSubject(真实主题角色):定义了代理角色所代表的真实对象。
Proxy(代理主题角色):含有对真实主题角色的引用,代理角色通常在将客户端调用传递给真实主题对象之前或者之后执行某些操作,而不是单纯返回真实的对象。

代码演示:

//抽象主题角色
//抽象的公共接口
class AbstractCommonInterface
{
public:
	virtual void run() = 0;
	virtual ~AbstractCommonInterface() {};
};
//真实主题角色
//真实的系统
class MySystem :public AbstractCommonInterface
{
public:
	void run() override
	{
		cout << "系统启动....." << endl;
	}
};
在这里插入代码片
//代理主题角色
//必须要有权限验证,不是所有人都能来启动我的系统,提供用户名和密码
class MySystemProxy :public AbstractCommonInterface
{
public:
	MySystemProxy(string mUserName, string mPassword) : mySystem(new MySystem){
		this->mUserName = mUserName;
		this->mPassword = mPassword;
	};

	~MySystemProxy(){ 
		if (mySystem != nullptr) {
			delete mySystem;
		}	
	};
	
	bool checkUserNameAndPassword() {
		if (mUserName == "admin" && mPassword == "123")
		{
			return true;
		}
		else {
			return false;
		}
	}

	void run() override
	{
		if (checkUserNameAndPassword())
		{
			this->mySystem->run();//调真实的服务系统
		}else {
			cout << "accout or password is error!" << endl;
		}
	}
private:
	MySystem* mySystem;//真实系统的指针
	string mUserName; //账号
	string mPassword; //密码
};

测试调用:

int main(int argc, char* argv[])
{
	AbstractCommonInterface* mySystemProxy = new MySystemProxy("admin","123");
	mySystemProxy->run();
	delete mySystemProxy;
	return 0;
}

输出结果:
在这里插入图片描述
代理模式类的UML图如下:
在这里插入图片描述

外观模式

根据迪米特法则,如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。
Facade模式也叫外观模式,是由GoF提供的23种设计模式中的一种。
Facade模式为一组有类似功能的类群,比如类库,子系统等待,提供一个一致的简单界面。这个一致的简单界面被称作Facade。
外观模式就是将复杂的子类系统抽象到同一个接口进行管理,外界只需要通过此接口与子类系统进行交互,而不必要直接与复杂的子类系统进行交互

角色和职责

Facade(外观角色):为调用方,定义简单的调用接口。
SubSystem(子系统角色):功能提供者。指提供功能的类群(模块或子系统)。

代码演示一:

子系统代码

//子系统 1
class SubSystem1
{
public:
	void run() {
		cout << "子系统一运行..." << endl;
	}
};

//子系统 2
class SubSystem2
{
public:
	void run() {
		cout << "子系统二运行..." << endl;
	}
};

//子系统 3
class SubSystem3
{
public:
	void run() {
		cout << "子系统三运行..." << endl;
	}
};

//子系统 4
class SubSystem4
{
public:
	void run() {
		cout << "子系统四运行..." << endl;
	}
};

外观类代码

class Facade
{
public:
	Facade() {
		pSystem1 = new SubSystem1;
		pSystem2 = new SubSystem2;
		pSystem3 = new SubSystem3;
		pSystem4 = new SubSystem4;
	}

	~Facade() {
		delete pSystem1;
		delete pSystem2;
		delete pSystem3;
		delete pSystem4;
	}

	void runSystem(){
		pSystem1->run();
		pSystem2->run();
		pSystem3->run();
		pSystem4->run();
	}

private:
	SubSystem1* pSystem1;
	SubSystem2* pSystem2;
	SubSystem3* pSystem3;
	SubSystem4* pSystem4;
};

注意:因为Facade类的成员变量SubSystem1/2/3/4类型的指针,而不是SubSystem1类型的实例是其成员变量,
所以这里Facade类和SubSystem1/2/3/4都不能称为关联。又因为Facade类的构造函数中,用到了SubSystem1/2/3/4类。
所以Facade类依赖于SubSystem1/2/3/4类。Facade类和SubSystem1/2/3/4类是依赖关系。
拓展:关联是“HAS”关系,依赖是“USE”关系 。A类关联B类,指的是B类对象作为A类的属性存在,称为“has”关系。
A类依赖B类,指的是B的对象作为A类的方法参数或者在A类的方法内 存在,称为“use”关系 。
测试调用代码

void test(){
	
	Facade* facade = new Facade;
	facade->runSystem();
}

int main(int argc, char *argv[])
{
	test()
	
	return 0;
}

针对上例的外观模式UML类图:
在这里插入图片描述

代码演示二:

根据类图,实现家庭影院外观模式
实现KTV模式:
开启时:电视打开,灯关掉,音响打开,麦克风打开,dvd打开。
关闭时:电视关掉,灯打开,音响关掉,麦克风关掉,dvd关掉。
实现游戏模式:
开启时:电视打开,音响打开,游戏机打开。
关闭时:电视关掉,音响关掉,游戏机关掉。

子系统角色:

//电视机
class Television
{
public:
	void On(){
		cout << "电视机打开...." << endl;
	}

	void Off(){
		cout << "电视机关闭...." << endl;
	}
};

//灯
class Light
{
public:
	void On(){
		cout << "灯打开...." << endl;
	}

	void Off(){
		cout << "灯关闭...." << endl;
	}
};

//音箱
class Audio
{
public:
	void On(){
		cout << "音箱打开...." << endl;
	}

	void Off(){
		cout << "音箱关闭...." << endl;
	}
};

//麦克风
class Microphone
{
public:
	void On(){
		cout << "麦克风打开...." << endl;
	}

	void Off(){
		cout << "麦克风关闭...." << endl;
	}
};

//DVD播放器
class DVDPlayer
{
public:
	void On(){
		cout << "DVD播放器打开...." << endl;
	}

	void Off(){
		cout << "DVD播放器关闭...." << endl;
	}
};

//游戏机
class Gamemachine
{
public:
	void On(){
		cout << "游戏机打开...." << endl;
	}

	void Off(){
		cout << "游戏机关闭...." << endl;
	}
};

外观角色:

//KTV模式
class KTVMode
{
public:
	KTVMode(){
		pTv = new Television;	
		pLight = new Light;	
		pAudio = new Audio;	
		pMicrophone = new Microphone;	
		pDvd = new DVDPlayer;	
	}
	
	~KTVMode(){
		delete pTv;	
		delete pLight;	
		delete pAudio;	
		delete pMicrophone;	
		delete pDvd;	
	}
	
	void OnKTV(){
		pTv->On();
		pLight->Off();
		pAudio->On();
		pMicrophone->On();
		pDvd->On();
	}

	void OffKTV(){
		pTv->Off();
		pLight->On();
		pAudio->Off();
		pMicrophone->Off();
		pDvd->Off();
	}

private:
	Television* pTv;
	Light* pLight;
	Audio* pAudio;
	Microphone* pMicrophone;
	DVDPlayer* pDvd;
};


//游戏模式
class GameMode
{
public:
	GameMode(){
		pTv = new Television;	
		pAudio = new Audio;	
		pGamemachine = new Gamemachine;	
	}
	
	~GameMode(){
		delete pTv;	
		delete pAudio;	
		delete pGamemachine;		
	}
	
	void OnGame(){
		pTv->On();
		pAudio->On();
		pGamemachine->On();
	}

	void OffGame(){
		pTv->Off();
		pAudio->Off();
		pGamemachine->Off();
	}

private:
	Television* pTv;
	Audio* pAudio;
	Gamemachine* pGamemachine;
};

测试调用:

//测试KTV模式
void testKTVMode()
{
	KTVMode* pKTVMode = new KTVMode;
	pKTVMode->OnKTV();//开启KTV模式
	//pKTVMode->OffKTV();//关闭KTV模式
}

//测试游戏模式
void testGameMode()
{
	GameMode* pGameMode = new GameMode;
	pGameMode->OnGame();//开启游戏模式
	//pGameMode->OffGame();//关闭游戏模式
}


int main(int argc, char *argv[])
{
	testKTVMode();
	//testGameMode();
	return 0;
}

针对上例的外观模式UML类图:
在这里插入图片描述

外观模式适用场景

1.复杂系统需要简单入口使用。
2.客户端程序与多个子系统之间存在很大的依赖性。
3.在层次化结构中,可以使用外观模式定义系统中每一层的入口,
层与层之间不直接产生联系,而通过外观类建立联系,降低层之间的耦合度。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

<蓝桥杯软件赛>零基础备赛20周--第13周--DFS剪枝

报名明年4月蓝桥杯软件赛的同学们&#xff0c;如果你是大一零基础&#xff0c;目前懵懂中&#xff0c;不知该怎么办&#xff0c;可以看看本博客系列&#xff1a;备赛20周合集 20周的完整安排请点击&#xff1a;20周计划 每周发1个博客&#xff0c;共20周。 在QQ群上答疑&#x…

docker安装nacos+mysql+配置网络

一、配置网络 为什么要配置网络&#xff1f;因为 Nacos 内要连接MySQL数据库的&#xff0c;我的 MySQL 数据库也是用 Docker启动的&#xff0c;所以2个容器间要通信是需要配置他们使用相同的网络。这个操作要在启动Nacos容器之前。 注意&#xff1a;这里配置的网络只在镜像内部…

zabbix6.4设置网络设备端口流量P95

P95概念&#xff1a; p95函数写法&#xff1a; 需要监控P95的设备如下&#xff1a; 先找到原来的端口接收发送速率的监控项&#xff1a; 可以看到他们归属于自动发现规则&#xff1a;端口表UP 找到自动发现规则&#xff1a; 点击创建监控项原型&#xff1a; 公式如下&#xff…

基于LLM大模型的信息提取指南

信息提取&#xff08;information Extraction&#xff09;是从文本或文档集合中自动检索与特定主题相关的特定信息的过程。 这通常涉及自然语言处理技术的使用。 使用自然语言处理来提取信息通常会导致构建复杂的逻辑&#xff0c;这些逻辑有时非常具体并且不能很好地概括。 好…

Linux例行性工作 at和crontab命令

1&#xff0c;例行性工作 例行性工作 —— 在某一时刻&#xff0c;必须要做的事情 —— 定时任务 &#xff08;比如&#xff1a;闹钟&#xff09; 例行性工作分为两种&#xff1a;“单一的例行性工作 at”和“循环的例行性工作 crontab” 2&#xff0c;单一执行的例行性工作 …

C 程序运行机制

1.编辑 编写C语言源程序代码&#xff0c;源程序文件以“.c”作为扩展名。 2.编译 将C语言源程序转换为目标程序(或目标文件)。如果程序没有错误&#xff0c;没有任何提示&#xff0c;就会生成一个扩展名为“.obj”的二进制文件。C语言中的每条可执行语句经过编译后最终都将被…

Go语言中的HTTP请求发送

在Go语言中&#xff0c;发送HTTP请求是一种常见的网络操作。Go语言的net/http包提供了强大的API&#xff0c;使开发者能够轻松地构建HTTP请求并处理响应。 下面我们将详细介绍如何使用Go语言发送HTTP请求&#xff0c;包括设置请求参数、处理响应状态码和头部信息、发送JSON数据…

中湖盐——健康盐,盐中贵族

祁连山古老的盐湖,有一个水晶女和玉莹郎的传说,他们来到凡间做盐为生,做出的盐像水晶玉莹一样纯净。直到有一天,始皇帝传旨修长城,玉莹和水晶不忍百姓疾苦,用相思之泪化为了水晶般的白盐;血肉精华冶炼成萤石般的盐根,造福一方。 雪水溶积汇入的盐湖,水天倒映,美不胜收,中湖盐坚…

Zero-Shot Learning—A Comprehensive Evaluation of the Good, the Bad and the Ugly

目录 背景知识why zero-shot learning?广义零样本学习设置 1 INTRODUCTION1.1 zero-shot learning——methods1.2 zero-shot learning——datasets1.3 zero-shot learning——evaluation protocol 2 RELATED WORK2.1 早期工作2.1.1 Attribute-based classification for zero-s…

STC8H8K蓝牙智能巡线小车——3.按键开关状态获取

电路分析 引脚为P37开关未按下时&#xff0c;P37是高电平开关按下时&#xff0c;GND导通&#xff0c;P37是低电平 编程思路 Driver目录中添加KEY.h文件&#xff0c;应包含引脚定义、开关GPIO实例化函数、开关状态获取函数以及当按下和未按下时执行不同的函数&#xff08;函数…

多级缓存架构(三)OpenResty Lua缓存

文章目录 一、nginx服务二、OpenResty服务1. 服务块定义2. 配置修改3. Lua程序编写4. 总结 三、运行四、测试五、高可用集群1. openresty2. tomcat 通过本文章&#xff0c;可以完成多级缓存架构中的Lua缓存。 一、nginx服务 在docker/docker-compose.yml中添加nginx服务块。…

全光谱护眼灯有哪些?寒假护眼台灯推荐

全光谱指的是包含了整个可见光谱范围以及部分红外和紫外光的光线。通常的白炽灯或荧光灯只能发出有限范围内的光波&#xff0c;而全光谱台灯通过使用多种类型的LED灯或荧光灯管来产生更广泛的光谱。这样的光谱更接近自然光&#xff0c;能够提供更真实的颜色还原和更好的照明效果…

Spring Cloud微服务基础入门

文章目录 发现宝藏前言环境准备创建第一个微服务1. 创建Spring Boot项目2. 创建微服务模块3. 编写微服务代码4. 创建一个简单的REST控制器 运行微服务 总结好书推荐 发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不…

懒得玩游戏--帮我做数独

目录 简介自动解数独思路核心思路输入解析打印 完整代码 简介 最近玩上了一款类似于数独的微信小程序游戏&#xff0c;名字叫数独趣味闯关&#xff0c;过了数独的关卡之后会给拼图&#xff0c;玩了几关之后摸清套路了就有点累了&#xff0c;但是还想集齐拼图&#xff0c;所以就…

为什么使用 atan2(sin(z), cos(z)) 进行角度归一化?

文章目录 为什么使用 atan2(sin(z), cos(z)) 进行归一化&#xff1f;为什么归一化后的角度等于原始角度&#xff1f; atan2 方法返回 -π 到 π 之间的值&#xff0c;代表点 (x, y) 相对于正X轴的偏移角度。这个角度是逆时针测量的&#xff0c;以弧度为单位。关于 atan2 函数为…

【第十四课】并查集(acwing-836合并集合 / 做题思路 /c++代码)

目录 错误思路(但能骗分emm)--邻接矩阵(可以跳过) 思路 存在的问题 代码如下 并查集 思路 代码如下 一些解释 错误思路(但能骗分emm)--邻接矩阵(可以跳过) 思路 刚看到这道题我自己做的时候&#xff0c;因为之前学的trie树的时候意识到使用二维数组的含义&#xff0c;…

群发邮件的免费软件?做外贸用什么邮箱好?

群发邮件的免费软件有哪些&#xff1f;好用的邮件群发软件&#xff1f; 在数字时代&#xff0c;邮件已成为人们沟通的主要方式之一。有时候&#xff0c;我们需要给大量的联系人发送信息&#xff0c;这时候&#xff0c;群发邮件就显得格外重要。接下来蜂邮就来探讨一下那些值得…

初学者必知的微软.NET6开发环境相关技术介绍

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;看到不少初学者在学习编程语言的过程中如此的痛苦&#xff0c;我决定做点什么&#xff0c;我小时候喜欢看小人书&#xff08;连环画&#xff09;&#xff0c;在那个没有电视、没有手机的年代&#xff0c;这是…

[我的rust付费栏目]rust跟我学(一)已上线

大家好&#xff0c;我是开源库get_local_info的作者带剑书生&#xff0c;get_local_info诞生半个月&#xff0c;现在已经获得500的下载量&#xff0c;并获社区日更前五名&#xff0c;后被西安城市开发者社区收录&#xff08;【我的Rust库】get_local_info 0.1.5发布_rust_科比布…

ChatGPT:人工智能划时代的标志(文末送书)

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;网络奇遇记、数据结构 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 一. 什么是ChatGPT?二. ChatGPT是如何工作的&#xff1f;三. ChatGPT的应用领域四. ChatGPT的优缺点…