11结构型设计模式——外观模式

news2024/9/24 1:24:38

一、外观模式简介

外观模式(Facade Pattern)是一种结构型设计模式,它提供了一个统一的接口来访问子系统中的一组接口,使得子系统的使用更加简单和方便。通过外观模式,可以将复杂的子系统封装在一个外观类(Facade)中,从而减少代码的耦合度,提高系统的可维护性和易用性。

外观模式的结构图

  1. 外观类(Facade):提供一个高层接口,简化了对子系统的操作。
  2. 子系统类(Subsystem Classes):实现具体的业务功能,通常这些类之间有复杂的依赖关系。

外观模式的核心概念

  1. 简化接口:外观模式将复杂的子系统接口封装在一个简单的外观类中,用户只需要与这个外观类交互,而不必直接使用复杂的子系统接口。

  2. 降低耦合度:通过引入外观类,外部代码与复杂的子系统解耦,从而减少系统间的依赖关系。

  3. 提高可维护性:因为外观模式提供了简化的接口,所以修改子系统的实现不会直接影响到使用外观类的代码,系统的维护和扩展变得更加方便。

二、外观模式的应用场景

1. 简化复杂系统的接口

当一个系统由多个子系统组成,每个子系统有自己的接口和功能时,外观模式可以提供一个统一的接口,简化系统的使用。例如:

  • 家庭影院系统:如前面所述,通过外观模式,可以将电视、音响、DVD播放器等设备的操作封装在一个简单的接口中,使得用户可以更轻松地控制整个家庭影院系统。

  • 图形库:图形库可能提供复杂的图形绘制功能,通过外观模式,可以将这些功能封装成一个简单的接口,方便应用程序的调用。

2. 减少系统间的耦合

外观模式通过引入外观类,使得系统的不同部分之间的耦合度降低。这样,即使子系统发生变化,外部代码也不会受到影响。例如:

  • 第三方库的集成:当集成第三方库时,外观模式可以封装这些库的复杂接口,使得应用程序只需与外观类交互,而不必处理第三方库的细节。

3. 提升代码的可维护性

外观模式有助于将复杂的子系统封装在一个单一的外观类中,从而提高代码的可维护性和可读性。例如:

  • 配置管理:当系统需要处理多个配置模块时,可以使用外观模式将这些模块封装在一个统一的配置管理类中,简化配置的管理和使用。

4. 构建高层接口

在构建一个大型应用程序时,外观模式可以用来提供高层接口,使得不同层次的功能可以更清晰地进行组织和调用。例如:

  • Web应用程序:在Web应用程序中,外观模式可以用来封装不同的服务,如用户管理、订单处理等,为控制器提供简洁的接口。

5. 提升系统的扩展性

通过引入外观类,可以在不修改现有代码的情况下扩展系统。例如:

  • 插件系统:在插件架构中,外观模式可以用来提供统一的插件接口,使得在添加或修改插件时,不必更改核心系统的实现。

6. 简化测试

在进行单元测试时,外观模式可以帮助创建一个简单的测试接口,从而简化测试的编写和维护。例如:

  • 测试复杂的业务流程:使用外观模式将复杂的业务流程封装在一个测试接口中,可以更方便地测试整个流程的正确性。

7. 过渡旧系统

在将旧系统迁移到新系统时,可以使用外观模式提供一个兼容的接口,使得新系统可以与旧系统进行交互,而不必修改旧系统的实现。例如:

  • 迁移到新的数据存储解决方案:在迁移数据库时,外观模式可以用来封装旧数据库的接口,使得应用程序可以继续正常工作,直到新数据库的迁移完成。

三、外观模式的设计方法

假设我们有一个复杂的家庭影院系统,包括电视、音响和DVD播放器、APP、CCTV。我们希望通过一个简单的接口来控制这个系统,而不必直接操作每个子系统。

facade.cpp

#include <iostream>
#include <string>

// 子系统
class TV {
public:
    void turnOn() { std::cout << "TV is now ON\n"; }
    void turnOff() { std::cout << "TV is now OFF\n"; }
};

class SoundSystem {
public:
    void turnOn() { std::cout << "Dolby Atmos Sound System is now ON\n"; }
    void turnOff() { std::cout << "Sound System is now OFF\n"; }
};

class DVDPlayer {
public:
    void turnOn() { std::cout << "DVD Player is now ON\n"; }
    void turnOff() { std::cout << "DVD Player is now OFF\n"; }
};

class TencentAPP {
public:
    void turnOn() { std::cout << "Tencent APP is now ON\n"; }
    void turnOff() { std::cout << "Tencent APP is now OFF\n"; }
};

class CCTV {
public:
    void turnOn() { std::cout << "CCTV is now ON\n"; }
    void turnOff() { std::cout << "CCTV is now OFF\n"; }
};

// 家庭影音
class HomeTheaterFacade {
public:
    HomeTheaterFacade(TV* tv, SoundSystem* soundSystem, TencentAPP* tencentAPP, CCTV* cctv)
        : tv_(tv), soundSystem_(soundSystem), tencentAPP_(tencentAPP), cctv_(cctv) {}

    void watchMovie() {
        std::cout << "Get ready to watch a movie...\n";
        tv_->turnOn();
        soundSystem_->turnOn();
        tencentAPP_->turnOn();
        cctv_->turnOn();
    }

    void endMovie() {
        std::cout << "Shutting down movie setup...\n";
        cctv_->turnOff();
        tencentAPP_->turnOff();
        soundSystem_->turnOff();
        tv_->turnOff();
    }

private:
    TV* tv_;
    SoundSystem* soundSystem_;
    TencentAPP* tencentAPP_;
    CCTV* cctv_;
};

// 电影院
class CinemaFacade {
public:
    CinemaFacade(TV* tv, SoundSystem* soundSystem, DVDPlayer* dvdPlayer)
        : tv_(tv), soundSystem_(soundSystem), dvdPlayer_(dvdPlayer) {}

    void watchMovie() {
        std::cout << "Get ready to watch a movie...\n";
        tv_->turnOn();
        soundSystem_->turnOn();
        dvdPlayer_->turnOn();
    }

    void endMovie() {
        std::cout << "Shutting down movie setup...\n";
        dvdPlayer_->turnOff();
        soundSystem_->turnOff();
        tv_->turnOff();
    }

private:
    TV* tv_;
    SoundSystem* soundSystem_;
    DVDPlayer* dvdPlayer_;
};

// 使用外观类
void doWorking(const int type) {
    if(type == 1) {
        TV tv;
        SoundSystem soundSystem;
        TencentAPP tencentAPP;
        CCTV cctv;

        HomeTheaterFacade homeTheater(&tv, &soundSystem, &tencentAPP, &cctv);
        homeTheater.watchMovie();  // 开始看电影
        homeTheater.endMovie();    // 结束电影
    }
    else if(type == 2) {
        TV tv;
        SoundSystem soundSystem;
        DVDPlayer dvdPlayer;

        CinemaFacade cinema(&tv, &soundSystem, &dvdPlayer);
        cinema.watchMovie();  // 开始看电影
        cinema.endMovie();    // 结束电影
    }
}

int main() {
    int type;
    std::cout << "Please select the Viewing mode: 家庭影音(1) or 电影院(2): ";
    std::cin >> type;
    doWorking(type);
    return 0;
}

运行效果

四、总结

外观模式的应用可以使看起来复杂的外观简化,使得系统看起来更加直观和方便。

外观模式的缺点

  1. 可能引入过度封装:外观类可能会过度封装,导致子系统的某些功能无法被直接访问。
  2. 不适用于所有场景:对于需要高度定制的场景,外观模式可能不适用,因为它提供的是统一的接口,可能无法满足所有特定需求。

外观模式的优点

  1. 简化代码:通过提供统一的接口,简化了复杂系统的使用。
  2. 降低耦合:外部代码不需要直接依赖于复杂的子系统。
  3. 提高灵活性:修改或扩展子系统的实现不会影响到使用外观类的代码。

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

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

相关文章

​​数据结构-树

n = 度数之和 + 1 n + x + y + z = x +2y +3z + 1

增加练习(修改获取练习的基本信息接口)

文章目录 1.sun-club-practice-api1.enums1.CompleteStatusEnum.java 2.req1.GetPracticeSubjectsReq.java 3.vo1.PracticeSubjectListVO.java 2.sun-club-practice-server1.PracticeSetController.java2.service1.PracticeSetServiceImpl.java 3.dao1.PracticeDao.java2.Pract…

HAL STM32 SG90舵机驱动控制

HAL STM32 SG90舵机驱动控制 &#x1f516;测试对象&#xff1a;STM32F103SG90舵机 &#x1f33c;功能实现&#xff1a;通过串口指令&#xff0c;控制SG90舵机转动到指定角度。 ✨在实际硬件舵机驱动过程中&#xff0c;使用SG90普通舵机空载运转情况下&#xff0c;电流在180mA…

验证集的loss比训练集大得多Val Loss is too large

这个跟数据集有关&#xff0c;不过可已通过clip减缓。 解决方法 nn.utils.clip_grad_norm_(self.Model.parameters(), max_norm5)

AtCoder Regular Contest 182 A~D

A.Chmax Rush!&#xff08;枚举&#xff09; 题意&#xff1a; 有一个长度为 N N N的整数序列 S S S。最初&#xff0c; S S S的所有元素都是 0 0 0。 同时给你两个长度为 Q Q Q的整数序列&#xff1a; P ( P 1 , P 2 , … , P Q ) P(P_1,P_2,\dots,P_Q) P(P1​,P2​,…,PQ…

AI产品经理修炼指南:从青铜到王者的逆袭之路

一、AI通识 1.1 AI产业结构 AI发展至今大致按照在产业结构上的分工不同产生了三种类型的公司&#xff0c;我们在转型时最好要先明确自己的优势及兴趣&#xff0c;来判断自己适合着眼于哪个层面的工作&#xff0c;从而进行针对性的学习和提升。 &#xff08;1&#xff09;行业…

Apache Flink细粒度资源管理原理

粗粒度资源管理 Apache Flink 1.1.4版本之前使用的是粗粒度的资源管理&#xff0c;即每个算子Slot Request所需要的资源都是未知的&#xff0c;Flink内部用UNKNOWN的特殊值来表示&#xff0c;这个值可以和任意资源规则的物理Slot匹配&#xff0c;站在Taskmanager的角度&#x…

打卡学习Python爬虫第二天|Web请求过程刨析

一、服务器渲染 服务器端渲染&#xff08;Server-Side Rendering&#xff0c;简称SSR&#xff09;是一种网页渲染技术。在这种技术中&#xff0c;服务器在接收到客户端的请求后&#xff0c;会生成页面的初始HTML内容&#xff0c;并将其发送给客户端。客户端浏览器接收到这些HT…

什么是BKP(备份寄存器)

一&#xff0c;什么是BKP 备份寄存器是42个16位的寄存器&#xff0c;可用来存储84个字节的用户应用程序数据。他们处在备份域里&#xff0c;当VDD电源被切断&#xff0c;他们仍然由VBAT维持供电。当系统在待机模式下被唤醒&#xff0c;或系统复位或电源复位时&#xff0c;他们也…

数据结构(6.2_2)——领接表法

领接表法&#xff08;顺序存储链式存储&#xff09; 代码&#xff1a; #define MaxVertextNum 10 //边(弧) typedef struct ArcNode {int adjvex;//边/弧指向哪个结点struct ArcNode* next;//指向下一条弧的指针//InfoType info;//边权值 }ArcNode; //顶点 typedef struct VNo…

小阿轩yx-Docker Swarm 管理

小阿轩yx-Docker Swarm 管理 容器编排部署工具 除 Google 推出的 Kubernetes 之外&#xff0c;还有 Docker 发布的 Swarm 与 Mesos 推出的 Marathon 案例一 Docker Swarm 群集部署 Docker 自诞生以来&#xff0c;容器特性以及镜像特性给 DevOps 爱好者带来很多方便很长时间…

基本数据统计分析上|集中位置统计量|分散程度统计量|分布形状统计量|常见概率分布

数据统计分析 现实生活中的许多数据都是随机产生的&#xff0c;如考试分数&#xff0c;月降雨量&#xff0c;灯泡寿命等。从统计角度来看&#xff0c;这些数据其实都是符合某种分布的&#xff0c;这种分布就是统计规律性 在数学建模过程中经常与数据打交道&#xff0c;需要进行…

【鸟哥的Linux私房菜(七)之文件IO】

文章目录 C语言文件IOC语言文件接口汇总什么是当前路径&#xff1f;默认打开的三个流 系统文件I/Oopenopen的第一个参数open的第二个参数open的第三个参数open的返回值 closewriteread 文件描述符fd文件描述符的分配规则重定向重定向的原理dup2添加重定向功能到minishell FILEF…

微乐校园pf

TOC springboot451微乐校园pf 绪论 1.1 研究背景 当前社会各行业领域竞争压力非常大&#xff0c;随着当前时代的信息化&#xff0c;科学化发展&#xff0c;让社会各行业领域都争相使用新的信息技术&#xff0c;对行业内的各种相关数据进行科学化&#xff0c;规范化管理。这…

vue3中引入插件报ts报错Could not find a declaration file for module

引入第三方组件时&#xff0c;下载了组件还是报ts错误Could not find a declaration file for module 解决办法 1. 下载这个插件的ts库&#xff08;有的没有ts库就用下面这种方式&#xff09; 2. 在src下创建一个shims-vue.d.ts文件&#xff08;简单直接&#xff0c;我用的这种…

DNS域名解析服务理论详解(域名结构、递归查询和迭代查询、CDN)

文章目录 DNS域名解析服务1.DNS系统的概念2.DNS系统的主要作用3.DNS的分布式数据结构和域名的结构4.DNS服务器类型4.1三种类型4.2分布式数据库4.3名词解释 5.CDN技术5.1CDN的基本原理5.2CDN的主要功能 6.DNS查询类型及原理6.1查询方式6.2查询原理过程6.3本地主机的DNS映射文件 …

基于Hadoop的物品租赁系统的设计与实现 9349a--论文

TOC springboot344基于Hadoop的物品租赁系统的设计与实现 9349a--论文 绪 论 1.1开发背景 随着网络的飞速发展&#xff0c;网络技术的应用越来越广泛&#xff0c;而信息技术的飞速发展&#xff0c;计算机管理系统的优势也逐渐体现出来&#xff0c;大量的计算机电子信息已经…

Python | 数据处理中常用的数据分布介绍

数据分布是指数据在统计图中的形状和特征&#xff0c;即数据取值的统计规律。在统计学中&#xff0c;数据分布是描述数据集中数值分布情况和规律的重要工具。通过数据分布&#xff0c;可以了解数据的集中程度、分散程度、偏态和峰态等信息&#xff0c;进而对数据进行合理的分析…

95后医疗行业女性转型记:如何成功踏入人工智能项目管理领域

分享目录 一、自我介绍&#xff0c;给大家分享一下拿到offer的心情吧 二、在整个求职转型陪跑营里&#xff0c;你收获最大的三个点是什么&#xff1f; 三、求职转行过程中&#xff0c;你遇到了哪些困难&#xff1f;七芊老师和强哥是怎么帮助你的&#xff1f;你是怎么走过来的…

Bellman_ford算法

使用Dijikstra算法求最短路问题&#xff0c;要求图中不能存在负长度的边&#xff0c;也就是负权边 为什么Dijikstra算法不能用来求含有负权边的图中的最短路问题&#xff1f; Bellman_ford算法 mention&#xff08;1&#xff09;&#xff1a; 没有挑选路径长度距离编号 1 结…