C++设计模式——Facade外观模式

news2025/4/21 21:45:13

一,外观模式简介

外观模式是一种结构型设计模式, 又称为门面模式,也是一种基于创建对象来实现的模式,为子系统中的各组接口的使用提供了统一的访问入口。

外观模式对外提供了一个对象,让外部客户端(Client)对子系统的访问都是基于该对象来完成,这个对象被称为外观对象(Facade Object),外观对象为子系统的访问提供了一个简单而且统一的入口。

客户端只需要关注Facade提供的对外接口的用法,而不需要关注子系统之间的复杂交互等细节。

举个例子,用户在电话购物的时候,可以不需要知道货物的流动和仓库处理等细节,只需要拨电话然后下单。

二,外观模式的结构

外观对象(Facade):它的底层封装了系统的各个子模块,向用户屏蔽了底层的复杂结构,在内部调用各种子系统的函数,对外提供一些简化的接口。

子系统对象(SubSystem):是组成复杂系统的各个独立模块,它们各自实现特定的功能,然后被Facade统一调用。

对应UML类图:

代码实现:

#include <iostream>
#include <vector>

using namespace std;

class SubSystem {
public:
    virtual void operation() = 0;
};

class SubSystem_A: public SubSystem{
public:
    void operation_A() {
        cout << "Exec operation_A from SubSystem_A" << endl;
    }
    void operation() override {
        operation_A();
    }
};

class SubSystem_B: public SubSystem{
public:
    void operation_B() {
        cout << "Exec operation_B from SubSystem_B" << endl;
    }
    void operation() override {
        operation_B();
    }
};

class SubSystem_C: public SubSystem{
public:
    void operation_C() {
        cout << "Exec operation_C from SubSystem_C" << endl;
    }
    void operation() override {
        operation_C();
    }
};

class Facade {
private:
    std::vector<SubSystem*> subsystems;
public:
    Facade() {
        subsystems.push_back(new SubSystem_A);
        subsystems.push_back(new SubSystem_B);
        subsystems.push_back(new SubSystem_C);
    }
    ~Facade() {
        for (auto* subsystem : subsystems) {
            delete subsystem;
        }
    }

    void executeOperations() {
        for (auto& subsystem : subsystems) {
            subsystem->operation();
        }
    }
};

int main() {
    Facade facade;
    facade.executeOperations();
    return 0;
}

运行结果:

Exec operation_A from SubSystem_A
Exec operation_B from SubSystem_B
Exec operation_C from SubSystem_C

三,外观模式的应用场景

系统集成:当多个组件或服务接口需要被统一管理和使用时,借助外观模式构建一个统一的入口。

API升级:当API升级时,为了兼容旧版本的API接口的使用,创建一个外观模式的对象,既可以对外提供新的API接口,又向后兼容旧的API接口。

开发第三方库或框架:针对大型的库或者框架的开发,为了简化用户的使用,隐藏底层实现,对外提供一个简单且统一的接口。

组件整合:为了让项目中兼容不同架构和使用方式的组件时,使用外观模式来规范化组件的调用方式。

四,外观模式的优缺点

外观模式的优点:

1.减少了需要客户端关注和处理的对象数,简化了接口的使用方式。

2.实现了子系统和客户端之间的解耦,使子系统的变更不会影响到客户端的调用方法。

3.降低了大型软件的编译难度,简化了大型软件在不同平台之间的移植过程。

4.对外提供接口的同时,可以针对单个子系统实现单独的优化和升级。

5.避免了客户端对内部底层逻辑的影响和破坏。

6.促进了子系统的模块化和可重用性。

外观模式的缺点:

1.对底层的过度包装会增加性能开销。

2.如果设计的不合理,会使重构变得有难度。

3.如果存在访问共享资源的情况,代码的编写不够严谨时,相同层次的子系统和子系统之间可能会互相影响。

4.子系统和子系统之间可能包含相同的功能,导致代码冗余。

五,代码实战

Demo1:模拟计算机的集成

#include <iostream>
#include <string>

//subSystem
class Monitor {
public:
    void turnOn() {
        std::cout << "Monitor turned on.\n";
    }
    void turnOff() {
        std::cout << "Monitor turned off.\n";
    }
};

//subSystem
class Keyboard {
public:
    void pressKey(int keyCode) {
        std::cout << "Pressed key: " << keyCode << ".\n";
    }
};

//subSystem
class CPU {
public:
    void start() {
        std::cout << "CPU started.\n";
    }
    void stop() {
        std::cout << "CPU stopped.\n";
    }
};

//Facade
class Computer {
private:
    Monitor monitor;
    Keyboard keyboard;
    CPU cpu;

public:
    Computer() {}

    void turnOnAndStart() {
        monitor.turnOn();
        keyboard.pressKey(13);
        cpu.start();
    }

    void shutDown() {
        cpu.stop();
        monitor.turnOff();
    }
};

int main() {
    Computer myComputer;
    myComputer.turnOnAndStart();
    myComputer.shutDown();

    return 0;
}

运行结果:

Monitor turned on.
Pressed key: 13.
CPU started.
CPU stopped.
Monitor turned off.

Demo1:模拟汽车的集成

#include <iostream>

// Subsystem 1
class Engine {
public:
       void Start()
       {
              std::cout << "Engine started" << std::endl;
       }
       void Stop()
       {
              std::cout << "Engine stopped" << std::endl;
       }
};

// Subsystem 2
class Lights {
public:
       void TurnOn() {
              std::cout << "Lights on" << std::endl;
       }
       void TurnOff(){
              std::cout << "Lights off" << std::endl;
       }
};

// Facade
class Car {
private:
       Engine engine;
       Lights lights;
public:
       void StartCar()
       {
              engine.Start();
              lights.TurnOn();
              std::cout << "Car is ready to drive" << std::endl;
       }
       void StopCar()
       {
              lights.TurnOff();
              engine.Stop();
              std::cout << "Car has stopped" << std::endl;
       }
};

int main()
{
       Car car;
       car.StartCar();
       car.StopCar();
       return 0;
}

运行结果:

Engine started
Lights on
Car is ready to drive
Lights off
Engine stopped
Car has stopped

六,参考阅读

https://www.geeksforgeeks.org/facade-method-c-design-patterns/

https://sourcemaking.com/design_patterns/facade

https://refactoringguru.cn/design-patterns/facade

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

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

相关文章

python小白兔做操 青少年编程电子学会python编程等级考试三级真题解析2021年12月

python小白兔做操 2021年12月 python编程等级考试级编程题 一、题目要求 1、编程实现 小白兔们每天早上都到草坪上做早操。做操前,首先要按照身高由矮到高排个队,下列代码实现了排队的功能。首先读取小白兔的只数,然后读取每只小白兔的身高信息,进行由矮到高的处理,最…

Python-井字棋

井字棋 1.设计登录界面1.1导入需要的工具包1.2窗口显示1.3登录界面图片显示1.6标签按钮输入框显示 2.登录功能实现2.1用户数据存储 2.2登录和注册2.2.1登录功能实现2.2.2注册功能实现 3.井字棋游戏3.1 导入需要的工具包3.2 窗口显示3.2 按钮标签显示3.3 棋盘设置初始状态3.4 游…

# 深入理解 Java 虚拟机 (二)

深入理解 Java 虚拟机 &#xff08;二&#xff09; Java内存模型 主内存与工作内存 所有的变量存储在主内存&#xff08;虚拟机内存的一部分&#xff09;每条线程有自己的工作内存&#xff0c;线程对变量的所有操作&#xff08;读取、赋值&#xff09;都必须在工作内存中进行…

前端 CSS 经典:图层放大的 hover 效果

效果 思路 设置 3 层元素&#xff0c;最上层元素使用 clip-path 裁剪成圆&#xff0c;hover 改变圆大小&#xff0c;添加过渡效果。 实现代码 <!DOCTYPE html> <html lang"en"><head><meta charset"utf-8" /><meta http-eq…

Linux-笔记 OverlayFS文件系统小应用 恢复功能

前言 通过另一章节 OverlayFS文件系统入门 中已经大致了解了原理&#xff0c;这里来实现一个小应用。通过前面介绍我们已经知道lowerdir是只读层&#xff0c;upperdir是可读写层&#xff0c;merged是合并层&#xff08;挂载点&#xff09;&#xff0c;那么我们可以利用这个机…

[leetcode] smallest-k-lcci. 最小的k个数

. - 力扣&#xff08;LeetCode&#xff09; class Solution { public:vector<int> smallestK(vector<int>& nums, int k) {int L 0, R nums.size() - 1;while (L < R){int left L, right R;int key nums[left];while (left < right){while (left &l…

【人工智能】—基于线性回归和多项式回归模型预测人均收入的研究

引言 随着人工智能技术的飞速发展&#xff0c;机器学习已成为数据分析和预测领域的重要工具。在众多机器学习算法中&#xff0c;线性回归和多项式回归因其模型简单、易于理解和实现而受到广泛应用。本文旨在探讨如何利用这两种回归模型对人均收入进行预测。线性回归模型以其简…

作 业 二

cs与msf权限传递 1、进入cs界面,首先来到 Cobalt Strike 目录下&#xff0c;启动 Cobalt Strike 服务端 2、用客户端进 3、建立监听 4、生成脚本文件 5、开启服务&#xff0c;让win_2012 下载木马文件并运行 6、显示已经获取到了win的权限 转到Metasploit Framework 7、进去m…

使用conda安装第三方包报错CondaSSLError

使用conda安装第三方包报错CondaSSLError 1. 报错信息2. 解决方法 1. 报错信息 错误描述&#xff1a;刚刚下载的 anaconda 在使用 conda 安装 pytorch 时报错&#xff08;CondaSSLError: OpenSSL appears to be unavailable on this machine. OpenSSL is required to download …

算法刷题日志 hot100 数组分类

文章目录 [169. 多数元素](https://leetcode.cn/problems/majority-element/)旋转图像215. 数组中的第K个最大元素](https://leetcode.cn/problems/kth-largest-element-in-an-array/description/)238. 除自身以外数组的乘积](https://leetcode.cn/problems/product-of-array-e…

线性代数基础概念:向量空间

目录 线性代数基础概念&#xff1a;向量空间 1. 向量空间的定义 2. 向量空间的性质 3. 基底和维数 4. 子空间 5. 向量空间的例子 总结 线性代数基础概念&#xff1a;向量空间 向量空间是线性代数中最基本的概念之一&#xff0c;它为我们提供了一个抽象的框架&#xff0c…

计算机视觉全系列实战教程 (十四):图像金字塔(高斯金字塔、拉普拉斯金字塔)

1.图像金字塔 (1)下采样 从G0 -> G1、G2、G3 step01&#xff1a;对图像Gi进行高斯核卷积操作&#xff08;高斯滤波&#xff09;step02&#xff1a;删除所有的偶数行和列 void cv::pyrDown(cv::Mat &imSrc, //输入图像cv::Mat &imDst, //下采样后的输出图像cv::Si…

Ceil()——向上取整函数

函数原型为&#xff1a; double ceil(double x); 大家可以在这个网站里更清晰的了解ceil - C Reference (cplusplus.com) 下面借助一道例题来帮助大家理解&#xff1a;牛牛的快递_牛客题霸_牛客网 (nowcoder.com) 我们分析题得知&#xff0c;在大于1的情况下&#xff0c;只要…

鸿蒙开发系统基础能力:【@ohos.screenLock (锁屏管理)】

锁屏管理 锁屏管理服务是OpenHarmony中系统服务&#xff0c;为锁屏应用提供注册亮屏、灭屏、开启屏幕、结束休眠、退出动画、请求解锁结果监听&#xff0c;并提供回调结果给锁屏应用。锁屏管理服务向三方应用提供请求解锁、查询锁屏状态、查询是否设置锁屏密码的能力。 说明&a…

OutOfMemoryError能被catch(Exception)捕获吗?

背景 写了一个 Kafka 消费者程序&#xff0c;Kafka 集群中数据量过大时&#xff0c;消费线程无故退出了&#xff0c;日志打印了心跳 OOM 异常信息&#xff1a; 但是消费线程里面的 run 方法里面明明包含了 catch (Exception e) &#xff0c;结尾信息没有打印异常&#xff0c;…

星坤Type-A连接器:创新快充技术,引领电子连接!

快速发展的电子时代&#xff0c;消费者对电子设备的性能和便利性有着更高的要求。特别是在充电和数据传输方面&#xff0c;快充技术和高速传输已成为市场的新宠。中国星坤公司推出的Type-A连接器系列&#xff0c;以其卓越的性能和创新的设计&#xff0c;满足了市场对高效、稳定…

考研数学复习(1/9):函数与极限

目录 函数与极限 1. 函数的概念 1.1 函数的定义 1.2 函数的表示方法 1.3 函数的分类 1.4 函数的运算 2. 极限的概念 2.1 极限的定义 2.2 极限的性质 2.3 极限的计算方法 2.4 极限的应用 3. 连续函数 3.1 连续函数的定义 3.2 连续函数的性质 3.3 连续函数的分类 …

从官方源码精简出第1个FreeRTOS程序

一、下载官方源码 1、打开百度搜索freerots&#xff0c;找到官网:FreeRTOS官网 2、将源码解压到没有中文目录的路径下 二、删减目录 1、删除FreeRTOS-Plus和tools 2、删除FreeRTOS/Demo下除CORTEX_STM32F103_Keil外的所有文件 3、删除FreeRTOS\Source\portable下除RVDS和MemM…

观星观景大屏呈现 实时拍摄长焦定格 当当狸智能天文望远镜TW2来啦

《宇宙的奇迹》中有这样一句话&#xff1a;“我们与那些遥远星系息息相关&#xff0c;无论它们是如何与我们天各一方&#xff0c;那些经过数十亿年旅行到达地球的光线&#xff0c;终究会把我们联系在一起”。 想象一下—— 等到繁星低垂&#xff0c;月光皎洁之时&#xff0c;…

景区智能厕所系统让旅游更便捷、更舒适

在旅游业蓬勃发展的今天&#xff0c;游客对于旅游体验的要求越来越高&#xff0c;而景区的基础设施建设也在不断创新和完善。其中&#xff0c;景区智能厕所系统的出现&#xff0c;无疑为游客带来了更加便捷、舒适的旅游体验。 一、智能厕所系统首先体现在其精准的定位和引导功能…