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

news2025/1/8 5:43:49

文章目录

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

代理模式

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

代理模式有以下三种角色:
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.coloradmin.cn/o/1388676.html

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

相关文章

Controller层自定义注解拦截request请求校验

一、背景 笔者工作中遇到一个需求&#xff0c;需要开发一个注解&#xff0c;放在controller层的类或者方法上&#xff0c;用以校验请求参数中(不管是url还是body体内&#xff0c;都要检查&#xff0c;有token参数&#xff0c;且符合校验规则就放行)是否传了一个token的参数&am…

旧衣回收小程序搭建:降低企业成本,提高回收效率!

在人们环保意识提升下&#xff0c;旧衣回收行业受到了大众的关注&#xff0c;同时旧衣回收具有门槛低、利润大的优势。在我国&#xff0c;回收行业不仅帮助普通人就业获利&#xff0c;还对环保做出了较大贡献。因此&#xff0c;旧衣回收行业成为了当下的热门商业模式&#xff0…

C#,入门教程(19)——循环语句(for,while,foreach)的基础知识

上一篇&#xff1a; C#&#xff0c;入门教程(18)——分支语句&#xff08;switch-case&#xff09;的基础知识https://blog.csdn.net/beijinghorn/article/details/124039953 一、for循环 当老师进入教室&#xff0c;从门口开始分别按行、列点名&#xff0c;看看哪位翘课&…

详细介绍如何使用T5实现文本摘要:微调和构建 Gradio 应用程序-含完整源码

对高效文本摘要的需求从未如此迫切。无论您是正在处理冗长研究论文的学生还是浏览新闻文章的专业人士,快速提取关键见解的能力都是非常宝贵的。T5 是一种因多项 NLP 任务而闻名的预训练语言模型,擅长文本摘要。使用 T5 的文本摘要与 Hugging Face API 是无缝的。然而,对 T5 …

二、基础篇 vue计算属性和侦听器

计算属性 模板内的表达式非常便利&#xff0c;但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。例如&#xff1a; <div id"example">{{ message.split().reverse().join() }} </div> 在这个地方&#xff0c;模板不…

【松叶漫话】来聊聊ChatGPT 和文心一言吧

两大AI助手的较量 在当今信息技术飞速发展的时代&#xff0c;人工智能助手成为我们生活中不可或缺的一部分。ChatGPT和文心一言作为两大代表性的AI助手&#xff0c;在智能回复、语言准确性、知识库丰富度等方面各有千秋。本文将就这两位AI助手的特点进行深入比较&#xff0c;为…

深入解析多目标优化技术:理论、实践与优化

本文深入探讨了多目标优化技术及其在机器学习和深度学习中的应用&#xff0c;特别聚焦于遗传算法的原理和实践应用。我们从多目标优化的基础概念、常见算法、以及面临的挑战入手&#xff0c;进而详细介绍遗传算法的工作原理、Python代码实现&#xff0c;以及如何应用于实际的机…

Java中常用的加密算法及其实现原理详解

目录 1、前言 2、对称加密算法 2.1 对称加密算法的工作原理 2.2 DES、AES、RC4算法的原理及其在Java中的实现 2.3 对称加密算法的优缺点 3、非对称加密算法 3.1 非对称加密算法的工作原理 3.2 RSA、DSA算法的原理及其在Java中的实现 3.3 非对称加密算法的优缺点 4、散…

AI工具推荐:开源TTS(文本生成语音)模型集合

XTTS TTS是一个语音生成模型&#xff0c;可以通过一个简短的6秒音频片段将声音克隆到不同的语言。它不需要大量的训练数据&#xff0c;也不需要耗费大量时间。TTS支持17种语言&#xff0c;可以进行声音克隆、情感和风格转移、跨语言声音克隆以及多语言语音生成等功能。XTTS-v2…

chatgpt实用技巧之二反问式提示

大家好&#xff0c;今天跟大家讲实用gpt的小技巧二、反问式提示 有时候不知道怎么给 GPT 提示词&#xff0c;这时候&#xff0c;就可以反问 GPT 如何更好地给提示词。如图片所示 更详细内容可以看下这篇&#xff1a; 按照 GPT 给出的&#xff1a;故事设定角色故事发展主题结局…

SSM框架学习笔记04 | SpringMVC

文章目录 一、SpringMVC简介二、 请求与响应1. 请求映射路径2. get请求与post请求3. 响应 二、REST风格1.简介 三、 SSM整合四、拦截器1. 定义拦截器2.配置拦截器3.拦截器执行顺序4.拦截器参数5.多个连接器工作流程分析6.拦截器链的运行顺序 一、SpringMVC简介 SpringMVC技术与…

锐意进取,蓬勃发展|爱基百客2023全景图

岁序更迭&#xff0c;2023年已悄然离去。对我们来说&#xff0c;这是充满挑战与机遇的一年。爱基百客作为一家专注于测序服务的公司&#xff0c;我们在这一年里经历了许多挑战&#xff0c;也取得了令人鼓舞的成绩。前面我们盘点了表观产品和单细胞产品&#xff0c;今天再邀您回…

判断交叉编译工具是否支持C++20的标准

写个任意的测试程序hello_world 执行 arm-linux-gnueabihf-g -stdc14 main.cpp arm-linux-gnueabihf-g -stdc17 main.cpp arm-linux-gnueabihf-g -stdc20 main.cpp没报错则代表支持&#xff0c;报错则不支持.

ChatGPT写论文最强指令

一、我正在寻找与&#xff08;XX主题&#xff09;相关的高质量学术资源&#xff0c;包括期刊文章、会议论文和研究报告。希望能获取这些文献的摘要和关键词&#xff0c;以便快速评估其相关性。同时&#xff0c;请根据文献的相关度或发布日期进行排序&#xff0c;并提供完整的引…

Unity 编辑器篇|(六)编辑器拓展EditorGUI类 (全面总结 | 建议收藏)

目录 1. 前言2. 参数3. 功能3.1 折叠菜单&#xff1a; Foldout3.2 检查 GUI 更改&#xff1a; BeginChangeCheck 、EndChangeCheck 监听值改变3.3 可禁用控件&#xff1a;BeginDisabledGroup 、EndDisabledGroup 是否禁用组中的控件3.4 下拉菜单&#xff1a;DropdownButton3.5 …

MySQL 查询数据

今天介绍一下 MySQL 数据库使用 SELECT 语句来查询数据。 语法 首先&#xff0c;介绍一下语法。以下为在 MySQL 数据库中查询数据通用的 SELECT 语法&#xff1a; SELECT column1, column2, ... FROM table_name [WHERE condition] [ORDER BY column_name [ASC | DESC]] [LI…

图解基础排序算法(冒泡、插入、选择)(山东大学实验二)

目录 ⚽前言&#xff1a; &#x1f3d0; 冒泡排序&#xff1a; 设定&#xff1a; 分类&#xff1a; 起源&#xff1a; 图解冒泡&#xff1a; 图中绿色&#xff1a; 图中橙色&#xff1a; 整体思路&#xff1a; 交换思路&#xff1a; 核心代码&#xff1a; &#x…

怎么在桌面查看备忘录新的提醒事项?方法教程

在这个信息爆炸的时代&#xff0c;我们每天都面临着无数的任务和提醒。作为一名忙碌的职场人&#xff0c;我经常需要依赖备忘录来记录重要的待办事项&#xff0c;以免遗漏。备忘录&#xff0c;就像我生活中的小助手&#xff0c;帮我记下工作会议、生日提醒、购物清单等等&#…

2.3数据链路层02

2.3 数据链路层 2.3.5 以太网 1、以太网概念 以太网是一种计算机局域网技术。IEEE&#xff08;电气与电子工程师协会&#xff1a;Institute of Electrical and Electronics Engineers&#xff09;组织的IEEE802.3标准制定了以太网的技术标准&#xff0c;它规定了包括物理层的…

matlab行操作快?还是列操作快?

在MATLAB中&#xff0c;通常情况下&#xff0c;对矩阵的列进行操作比对行进行操作更有效率。这是因为MATLAB中内存是按列存储的&#xff0c;因此按列访问数据会更加连续&#xff0c;从而提高访问速度。 一、实例代码 以下是一个简单的测试代码&#xff0c; % 测试矩阵大小 ma…