外观模式【结构型模式C++】

news2024/12/23 11:59:03

1.概述

       外观模式是一种结构型设计模式, 能为程序库、 框架或其他复杂类提供一个简单的接口。

2.结构  

  • 外观角色(Facade):为多个子系统对外提供一个共同的接口,知道哪些子系统负责处理请求,将客户端的请求转发给适当的子系统对象。
  • 附加外观 (Additional Facade): 类可以避免多种不相关的功能污染单一外观, 使其变成又一个复杂结构。 客户端和其他外观都可使用附加外观(非必须,根据实际情况可选)。
  • 子系统角色(SubSystem):实现子系统的功能,处理外观角色指派的任务。客户可以通过外观角色访问它。子系统在整个系统中可以是一个或多个模块,每个模块都有若干类组成,这些类可能相互之间有着比较复杂的关系。
  • 客户角色(Client):调用外观角色访问各个子系统的功能

3.实现 

       外观模式模式不但重要,而且其应用也非常广泛,如在软件项目中,我们做多表数据更新时,业务逻辑层(Service层)数据访问层(DAO层)的调用可能包含多个步骤,除此之外还要进行事务处理,最终统一对外提供一个update()方法,如此一来上层(如控制器Controller层)便可一步调用。软件模块应该只专注于各自擅长的领域,合理明确的分工模式才能更好地整合与共享资源。这正是外观模式所解决的问题,其中外观门面类对子系统的整合与共享极大地保证了用户访问的便利性。

3.1 实例类比

      现在以电脑启动过程为例,以便进一步说明外观模式。为了用户使用方便,电脑开机按钮可以控制电脑所有硬件和系统软件的启动和关闭。如果没有开机按钮,我们(客户端)需要采用最原始的方式一步一步的操作HardDrive 类、Memory 类、Processor 类方法实现启动,采用外观模式即按钮Computer类中的方法,直接调用Operation方法即可完成电脑的启动

3.2 具体实现
#include <iostream>
#include <string>


//子系统/子模块1
class HardDrive {
public:
	std::string Operation() const {
		return "HardDrive: Ready!\n";
	}
	// ...
	std::string ReadData() const {
		return "Guide loading startup data...\n";
	}
};

//子系统/子模块2
class Memory {
public:
	std::string Operation() const {
		return "Memory: Ready!\n";
	}
	// ...
	std::string LoadOS() const {
		return "Load initialization system...\n";
	}
};

//子系统/子模块3
class Processor {
public:
	std::string Start() const {
		return "Enter user usage mode...\n";
	}
};


//外观角色 具体为电脑启动按钮或关闭
class Computer {
protected:
	HardDrive* hardDrive;
	Memory   * memory;
	Processor* processor;


public:	
	Computer(
		HardDrive *hardDrive = nullptr,
		Memory *memory = nullptr,
		Processor* processor = nullptr) {
		this->hardDrive = hardDrive;
		this->memory = memory;
		this->processor = processor;
	}
	~Computer() {
		delete hardDrive;
		delete memory;
		delete processor;
	}
	
	std::string Operation() {
		std::string result = "computer is starting .....\n";
		result += this->hardDrive->Operation();
		result += this->memory->Operation();
		result += "computer orders model to perform the action:\n";
		result += this->hardDrive->ReadData();
		result += this->memory->LoadOS();
		result += this->processor->Start();
		return result;
	}
};

//客户端
void ClientCode(Computer *facade) {
	// ...
	std::cout << facade->Operation();
	// ...
}

int main() {
	HardDrive *hardDrive = new HardDrive;
	Memory *memory = new Memory;
	Processor* processor = new Processor;
	Computer *facade = new Computer(hardDrive, memory, processor);
	ClientCode(facade);

	delete facade;

	return 0;
}
3.3 运行结果

 

4.外观模式优缺点

优点:

  • 减少相互依赖:实现了子系统与客户之间的松耦合关系,子系统的组件变化不会影响到调用它的客户类,只需调整外观类即可。
  • 提高灵活性:对客户屏蔽子系统组件,减少了客户处理的对象数目,客户代码使用子系统使用起来更加容易。但并不妨碍客户直接访问子系统。
  • 提高安全性:更好地划分访问层次。
  • 遵循迪米特法则,即最少知道原则。

缺点:

  • 当增加子系统和扩展系统行为时,可能容易带来未知风险。
  • 不能很好地限制客户使用子系统类,如果对客户访问子系统类做太多的限制则减少了可变性和灵活性。
  • 在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”。
  • 某些情况下可能违背单一职责原则。

5 应用场景

  • 减少对子系统的依赖性
  • 子系统相对独立且越来越复杂,增加门面模式提供接口
  • 构建多层系统结构,利用门面对象作为每层的入口,简化层间调用

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

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

相关文章

Python使用设计模式中的建筑模式将数据写入Excel且满足条件内容标红

对于这个任务&#xff0c;适合使用"Builder"设计模式。Builder模式的主要目的是将对象的构建与其表示分离&#xff0c;以便相同的构建过程可以创建不同的表示。在这个情况下&#xff0c;我们需要一个构建器来逐行构建Excel表格&#xff0c;并根据给定的数据添加相应的…

MySQL--对于库的操作对于表的操作

一、库的查看创建删除 库的查看 show databases; 库的创建&#xff08;创建一个test1数据库&#xff09; create database test1; 同样&#xff0c;我们另起一个root会话&#xff0c;并执行 cd /var/lib/mysql 然后发现多了一个test1目录 删除库&#xff08;删除test1数…

Java 为什么设计成 “String” 不能用 “==” 比较值?

Java中的String是一种特殊的对象类型&#xff0c;用于表示字符串。在Java中&#xff0c;String对象的创建和比较是一个重要的话题&#xff0c;其中&#xff0c;操作符在比较String对象时有着特殊的行为。为了了解Java为什么设计成String不能用比较值&#xff0c;需要深入探讨Ja…

VMamba原理

为了解决模型中的方向敏感性问题&#xff0c;我们引入了交叉扫描模块&#xff08;CSM&#xff09;。该模块能够遍历图像空间域&#xff0c;将任意视觉图像转化成有序序列。 VMamba降低注意力机制复杂度的概念来源于“具有选择性的扫描状态空间序列模型”&#xff08;Selective…

力扣33. 搜索旋转排序数组

Problem: 33. 搜索旋转排序数组 文章目录 题目描述思路复杂度Code 题目描述 思路 1.初始化左右指针&#xff1a;首先&#xff0c;定义两个指针left和right&#xff0c;分别指向数组的开始和结束位置。 2.计算中间值&#xff1a;在left和right之间找到中间位置mid。 3.比较中间值…

人工智能分割分类model:nnUnet-paddle

文章目录 神经网络nnUnet和paddle都需要在Ubuntu下进行安装PaddleProject 神经网络 开源来自https://github.com/MIC-DKFZ/nnUNet 自建了仓库&#xff0c;但还不会用 来自 mmsegmentation有空去了解 . MICCAI 2020 也是用到这个网络 paddle上的是不是不能用… nnUnet和pad…

废旧锂电池污水如何处理

废旧锂电池中含有多种潜在有害物质&#xff0c;因此正确处理废旧锂电池产生的污水对环境保护至关重要。以下是处理这种污水的几个关键步骤&#xff1a; 收集与预处理&#xff1a; 废旧锂电池应首先在干燥、通风良好的环境中安全收集&#xff0c;避免污水泄漏。在开始处理之前&…

Ansible-Tower安装破解

主机IP地址版本Ansible192.168.169.2042.9.1Tower192.168.169.2043.6.2 基础环境 systemctl disable firewalld --now && setenforce 0 sed -i s/SELINUXenforcing/SELINUXdisabled/g /etc/selinux/config mv /etc/yum.repos.d/CentOS-* /tmp/ curl -o /etc/yum.repo…

【UE5】动态播放媒体

最近项目中有一个需求&#xff0c;需要将场景中的42块屏幕都显示媒体内容&#xff0c;想着如果每一块屏幕都创建一个MediaPlayer资产、一个MediaSource资产、一个MediaTexture资产及创建对应的Material&#xff0c;就是4*42168个资产需要维护了&#xff0c;所以想着就全部采用动…

数据库|TiDB-Server API的高效应用指南

一、API介绍 1.Status 显示TiDB 连接数、版本和git_hash 信息 tidb-server_ip:status_port/status { "connections": 0, "version": "5.7.25-TiDB-v6.1.1", "git_hash": "5263a0abda61f102122735049fd0dfadc7b7f822" } 2.St…

C语言:文件操作(中)

片头 嗨&#xff01;小伙伴们&#xff0c;大家好&#xff01;在上一篇中&#xff0c;我们学习了C语言&#xff1a;文件操作&#xff08;上&#xff09;&#xff0c;在这一篇中&#xff0c;我们将继续学习文件操作&#xff0c;准备好了吗&#xff1f;Ready Go ! ! ! 文件的顺序…

宽字符的来历:从ASCII到Unicode,C语言中的宽字符处理

目录 一、ASCII编码&#xff1a;字符世界的开篇 二、Unicode与宽字符的诞生 宽字符类型与宽字符串 三、C语言中的宽字符处理函数 四、宽字符与多字节字符 结语 在计算机科学的发展历程中&#xff0c;字符编码经历了从简单到复杂、从单一语言到全球多语种支持的演变过程。…

【AGX】Ubuntu20.04 + ROS_ noetic+ 大疆Mid360激光 雷达评测

大家好&#xff0c;我是虎哥&#xff0c;最近组装机器人&#xff0c;使用到了大疆孵化的圳市览沃科技有限公司&#xff08;简称Livox览沃科技&#xff09;推出的觅道系列全新混合固态激光雷达Mid-360&#xff0c;顺便试试效果&#xff0c;也记录一下使用入门过程。 "觅道M…

323_C++_QT_使用QProcess执行cmd解压tar.gz等等其他压缩包文件到指定目录,不需要外部库,QT自带API的就行

// decompressPath : 解压到此目录 // fileName : 解压的tar.gz文件名executeCommand(decompressPath , QString::fromStdString(fileName));// 开始解压 void executeCommand

基于Springboot的医疗服务系统

基于SpringbootVue的医疗服务系统设计与实现 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringbootMybatis工具&#xff1a;IDEA、Maven、Navicat 系统展示 用户登录 首页 公告信息 医疗地图 医疗药品 普通村民管理 乡村医生管理 公告信息管理 乡村诊…

Microsoft Access Database使用

“小规模数据用Excel&#xff0c;大规模数据用Access。” 当涉及到大规模数据时&#xff0c;使用excel非常的卡顿&#xff0c;使用access就不会出现这个问题。 一、常用操作 1.新建一个数据库 直接右键&#xff0c;新建 access数据库 2.excel内容导入到access中&#xff08;成…

基于H.264的RTP打包中的组合封包以及分片封包结构图简介及抓包分析;FU-A FU-B STAP-A STAP-B简介;

H.264视频流的RTP封装类型分析&#xff1a; 前言&#xff1a; 1.RTP打包原则&#xff1a; RTP的包长度必须要小于MTU(最大传输单元)&#xff0c;IP协议中MTU的最大长度为1500字节。除去IP报头&#xff08;20字节&#xff09;、UDP报头&#xff08;8字节&#xff09;、RTP头&a…

unittest_parameterized批量测试测试用例

import unittest from parameterized import parameterizeddef add(x, y):return xy"""问题&#xff1a;如果有三组数据需要测试&#xff1f;[(1,1,2), (1,2,3), (0,3,3)] """def get_data():return [(1, 2, 3), (3, 0, 3), (2, 1, 3)]# 定义测试…

002 springCloudAlibaba Sentinel流控-关联

当与A关联的资源B达到阀值后&#xff0c;就限流A自己 文章目录 FlowLimitController.javaSentinelServerApplication.javaServletInitializer.javaapplication.yamlpom.xmlpom.xml 启动Sentinel8080 - java -jar sentinel-dashboard-1.7.0.jar 启动微服务8401 启动8401微服务…

微信开发api、微信视频号开发

接口地址&#xff1a; http://api.videostui.com/finder/v2/api/login/checkLogin 接口说明 获取到登录二维码后需每间隔5s调用本接口来判断是否登录成功新设备登录平台&#xff0c;次日凌晨会掉线一次&#xff0c;重新登录时需调用获取二维码且传appId取码&#xff0c;登录成…