AI Chat 设计模式:8. 门面(外观)模式

news2024/11/30 5:49:49

本文是该系列的第八篇,采用问答式的方式展开,问题由我提出,答案由 Chat AI 作出,灰色背景的文字则主要是我的一些思考和补充。

问题列表

  • Q.1 请介绍一下门面模式
  • A.1
  • Q.2 该模式由哪些角色组成呢
  • A.2
  • Q.3 举一个门面模式的例子
  • A.3
  • Q.4 可否做个比喻,来说明一下门面模式
  • A.4
  • Q.5 我感觉门面模式更像一种设计思想,而非设计模式,你认为呢
  • A.5

Q.1 请介绍一下门面模式

A.1

门面模式(Facade Pattern)是一种结构型设计模式,它提供了一个简单的接口,用于统一封装子系统中的一组接口,并将其展示给客户端。门面模式的目的是通过隐藏子系统的复杂性,简化客户端与子系统之间的交互。

在门面模式中,门面类(Facade Class)充当了一个中介者的角色,它知道如何处理客户端的请求,并将其委派给相应的子系统进行处理。门面类对外暴露的接口是简单的、易于理解的,客户端只需通过门面类与子系统进行交互,无需直接和子系统的各个组件打交道。

使用门面模式可以带来以下几个优点:

  1. 简化客户端与子系统之间的交互:门面模式提供了一个统一的接口,让客户端更容易使用子系统,而无需了解其复杂的内部实现。

  2. 将客户端与子系统解耦:门面类起到了解耦的作用,客户端只需与门面类进行交互,而完全不需要了解子系统的实现细节。这样可以降低客户端与子系统之间的依赖性,使得系统更加灵活。

  3. 提高了代码的可维护性和扩展性:通过门面模式,可以将子系统的功能进行封装和组织,使得系统的结构更加清晰。这样,当需要修改或扩展子系统时,只需修改门面类而不影响到客户端。

需要注意的是,门面模式并不是为了引入新的功能,而是为了提供一个简单的接口来使用现有的子系统。如果需要引入新的功能,还是需要修改子系统本身。

总而言之,门面模式在软件开发中可以起到封装和简化的作用,提高了系统的可维护性和灵活性,同时也使得客户端的代码更加简洁易懂。

门面模式也称外观模式。主要就两个作用:(1)解耦客户端与子系统;(2)简化客户端操作。

Q.2 该模式由哪些角色组成呢

A.2

门面模式由以下几个主要的角色组成:

  1. 门面(Facade):门面是门面模式的核心角色,它提供了一个统一的接口,用于封装子系统中的一组接口。门面类知道哪些子系统负责处理请求,可以将客户端的请求委派给相应的子系统处理

  2. 子系统(Subsystems):子系统是门面模式中的各个组件,它们是实现子系统功能的具体类或对象。子系统可以是一个或多个相关的类的集合,每个类对应一个具体的子系统。

  3. 客户端(Client):客户端是使用门面模式的外部代码,它通过门面类来与子系统进行交互。客户端不需要直接与子系统中的具体类进行通信,而是通过调用门面类暴露的简单接口来完成操作。

  4. 可选: 上下文(Context):上下文是指在某些情况下门面模式中使用的附加角色。上下文可以包含一些与操作相关的额外信息或状态,并将其传递给门面类的方法。

总的来说,门面模式是由门面、子系统和客户端组成的。门面类提供了一个简单的接口,封装了子系统的复杂性,使得客户端可以更轻松地与子系统进行交互。客户端通过门面类来调用所需的子系统功能,而不需要与具体的子系统组件直接交互。

各组成角色间的交互大概如下,客户端只需要与门面接触。如果没有门面,那么客户端将与子系统直接交互,这就要求客户端知道子系统的信息。这不符合迪米特法则,也即一个对象应尽可能对另一个对象了解的少。

这里是引用

Q.3 举一个门面模式的例子

A.3

好的,我们以一个计算机系统的启动过程为例来演示门面模式的应用。

在一个计算机系统中,启动过程可能涉及多个子系统,例如 CPU 初始化、内存管理、硬盘加载等。为了简化客户端与各个子系统之间的交互,我们可以使用门面模式。

首先,我们定义各个子系统的类,如 CPU 类、Memory 类和 HardDrive类,它们分别代表 CPU 初始化、内存管理和硬盘加载等功能。

// CPU子系统类
class CPU {
public:
    void initialize() {
        // CPU初始化操作
    }
};

// Memory子系统类
class Memory {
public:
    void allocateMemory() {
        // 分配内存操作
    }
};

// HardDrive子系统类
class HardDrive {
public:
    void load() {
        // 加载硬盘操作
    }
};

接下来,我们定义门面类 ComputerFacade,它封装了上述三个子系统,并提供一个简单的接口供客户端调用。

// 门面类
class ComputerFacade {
private:
    CPU cpu;
    Memory memory;
    HardDrive hardDrive;

public:
    void start() {
        cpu.initialize();
        memory.allocateMemory();
        hardDrive.load();
        // 其他启动操作
    }
};

最后,客户端可以通过ComputerFacade来启动整个计算机系统,而无需直接与各个子系统进行交互。

int main() {
    // 创建计算机门面对象
    ComputerFacade facade;

    // 启动计算机系统
    facade.start();

    return 0;
}

通过上述代码,我们可以看到,客户端只需通过调用ComputerFacadestart()方法来启动计算机系统,而无需了解具体的子系统实现。门面模式将启动过程中涉及的子系统封装起来,简化了客户端与子系统之间的交互。

这就是一个简单的使用 C++ 实现的门面模式的例子。通过门面模式,我们可以将复杂的系统组织起来,提供一个简单的接口给客户端使用,同时保持系统的灵活性和可维护性。

上面这个例子,通过引入门面,不仅解耦了客户端与子系统,还简化了客户端调用。

在有些情况下,可能无法像该例子中的 start() 方法,里面封装了多个子系统方法,无法简化客户端的调用。很可能需要将多个子系统的多个方法分别封装,比如将 CPU 类的 initialize() 方法、Memory 类的 allocateMemory() 方法和 HardDrive类的 load() 方法分别放到一个方法中,门面类中总共存在 3 个方法。此时,门面模式并不能简化客户端的调用,需要考虑是否仍然使用门面模式,此时主要关注点在是否要解耦客户端与子系统。

Q.4 可否做个比喻,来说明一下门面模式

A.4

当然可以!我们可以使用一个酒店前台的比喻来说明门面模式。

想象一下你去一家酒店,你需要完成多个事情,比如办理入住手续、领取房卡、查询酒店设施等。如果酒店没有一个前台接待员,你将需要直接与各个部门打交道,分别去办理手续、领取钥匙等。这样会让整个过程非常麻烦和复杂。

现在,如果酒店引入了一个前台接待员作为门面,你只需要与前台接待员进行交互,他会帮你处理所有的事情。你只需提供你的需求,比如办理入住手续,前台接待员会代替你与不同的部门沟通,完成办理入住手续、领取房卡等操作。这样,你只需要与前台接待员打交道,大大简化了整个流程。

在这个比喻中,酒店前台接待员就是门面类,各个部门(办理手续、领取房卡等)就是子系统。门面类封装了各个子系统的操作,并提供一个简单的接口给客户(你)使用,隐藏了各个子系统的复杂性。你只需与门面类进行交互,无需直接与各个子系统进行交互。

这个比喻可以帮助我们理解门面模式的核心思想:通过引入一个门面类,将复杂的子系统封装起来,为客户端提供一个便捷、简单的接口,隐藏了子系统的复杂性。

引入接待员(门面)之前,住户要事事亲为,引入后事情找接待员来做就行。
这里是引用

Q.5 我感觉门面模式更像一种设计思想,而非设计模式,你认为呢

A.5

你提出的观点是正确的。门面模式确实可以被视为一种设计模式,但更重要的是它代表了一种软件设计和架构的思想。

在软件开发中,门面模式的主要目标是提供一个简化的接口,隐藏系统的复杂性,使得客户端能够更轻松地使用系统的功能。它通过创建一个门面类,该类封装了底层组件或子系统的复杂操作,并提供一个高层次的接口给客户端使用。

门面模式的思想是通过提供简单、一致的接口来简化复杂系统的使用,将客户端与底层实现解耦,提供更好的可维护性和灵活性。这种思想可以在软件开发的各个领域和层次中应用,并有助于提高代码的可读性、可维护性和可扩展性。

所以你是对的,门面模式更像是一种软件设计和架构的思想,它的本质是提供简化的接口,使得客户端能够更轻松地使用复杂系统的功能。设计模式只是这种思想的一种具体实现方式。

设计模式通常是经过多次验证和广泛应用的可重复使用的解决方案,也就是前人思考的结晶。我们学设计模式,更多的是他们的设计思想,所以不用纠结门面模式到底是不是严格意义上的设计模式。

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

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

相关文章

vue的computed复习

1.复杂 data 的处理方式 三个案例:  案例一:我们有两个变量: firstName 和 lastName ,希望它们拼接之后在界面上显示;  案例二:我们有一个分数: score  当 score 大于 60 的时候&#xf…

云拨测全面升级丨单次拨测低至 0.001 元

作者:少焉 随着云原生、微服务技术的发展,可观测需求变得越来越强烈,作为可观测技术的重要能力之一,云拨测(Synthetics Monitor)由于其零侵入、开箱即用、主动式监测手段,也受到很多用户的青睐…

arcgis建筑物平均高度

主要用到相交和属性表的汇总功能。 路网 建筑物栋 相交结果 右键,bh列汇总 原始块有392,这里只有389,说明有的地块没有建筑,所以应该将表连接到原始街区上检查是否合理,以及随机验证一个结果是否正确。 连接结果&…

【问题总结】基于docker-compose实现nginx转发redis

目录: 文章目录 需求简介:Q1: nginx的http模块和http模块有什么不同Q2: 可以都使用stream模块进行配置吗 Docker环境下如何转发1 修改docker-compose2 修改nginx.conf3 测试连接 需求简介: 需要在192.168.3.11的ngnix上,转发192.…

wordpress 导入数据后 为什么总是跳转到安装页面

在WordPress导入数据后跳转到安装页面的问题可能由以下原因引起: 数据库连接问题:在导入数据之前,确保您的WordPress配置文件中的数据库连接信息正确且完整。打开 wp-config.php 文件,确保数据库的名称、用户名、密码和主机信息是…

springboot整合spring security的简单入门案例

一 工程结构 二 配置操作 2.1 pom文件配置 <!-- Spring Security依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency> 2.2 config配置 Config…

vue中预览pdf

情况一 如果后端返回的pdf地址&#xff0c;粘贴到浏览器的url框中&#xff0c;可以在浏览器中直接进行预览的&#xff0c;那么我们就用window.open&#xff0c;或 a标签&#xff0c;或iframe标签通过设置src进行预览即可 法1&#xff1a;可以直接使用window.open&#xff08;…

css学习知识总结

一、css与html连接&#xff1a; 可以将css语句放在html内部&#xff0c;一般放在<head>之下&#xff0c;定义在<style>中&#xff0c;格式一般是一个“.”然后加上一个“名称”再加上一个“{}”&#xff0c;再在“{}”内部定义具体的语句。 二、调整元素 2.1 字体…

网络 socket

文章目录 概念和 TCP、UDP 区别和 HTTP 区别 概念 为网络通信提供的接口&#xff0c;定义了应用程序如何访问网络资源、如何发送和接收数据等&#xff0c;Socket 是一个包含了IP地址和端口号的组合&#xff0c;当一个应用程序想要与另一个应用程序通信时&#xff0c;它会向特定…

6.3.5 利用Wireshark进行协议分析(五)----捕获并分析ICMP报文

6.3.5 利用Wireshark进行协议分析&#xff08;五&#xff09;----捕获并分析ICMP报文 一、捕获ICMP报文 打开Wireshark&#xff0c;选择网络接口并点击开始按钮。分组列表面板不断刷新抓渠道的数据包&#xff0c;为了过滤出我们所要分析的ICMP报文&#xff0c;我们在过滤框中输…

线程池学习(六)线程池状态转化

线程池状态定义 // runState is stored in the high-order bits // 线程池创建之后的初始状态&#xff0c;这种状态下可以执行任务private static final int RUNNING -1 << COUNT_BITS; // 线程池不再接收新的任务&#xff0c;但是会将队列中的任务执行完 private s…

Go-新手速成-流程语句

1if Go的if不建议写&#xff08;&#xff09;&#xff0c;over //if条件判断age : 16if age < 18 {fmt.Println("未成年")} 2for循环 Go摈弃了while和do while 循环&#xff0c;因为他做到了极简(也不要括号) 这么写可以 total : 0for i : 0; i < 100; i {…

41:canvas - 下

一、转换 转换 在canvas内&#xff0c;也可以像css一样有一些类似于css2D转换的效果 位移 语法&#xff1a;ctx.translate(x, y)注意&#xff1a;一定要在绘制&#xff08;描边或填充&#xff09;之前&#xff0c;进行位移 缩放 语法&#xff1a;ctx.scale(x, y)注意&…

Servlet的过滤器

过滤器: 使用传统的方式需要在每个页面进行验证造成代码的冗余功能重复麻烦过滤器【统计进行验证、鉴权、日志、事务】拦截请求、过滤响应 配置一个Servlet package com.sparrow.servlet;import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; im…

华为鲲鹏920 aarch64 版本 Ambari HDP 下载地址

声明&#xff1a;为有效缓解各位同行兄弟们的痛&#xff0c;特推出此文 本文能够适配兼容 华为鲲鹏920 aarch64 版本&#xff0c;仅限 CentOS7、openEuler20.03-LTS 操作系统 以下是详细下载地址 1、CentOS7 aarch64版本 CentOS7 aarch64 https://mirrors.huaweicloud.com/…

C# 抽象类和接口详解

参考视频链接&#xff1a;https://www.bilibili.com/video/BV13b411b7Ht?p27&vd_source10065785c7e10360d831474364e0d3e3 代码的进化与重构&#xff0c;从基本代码的讲解到逐步抽象成抽象类和接口。 文章目录 最初定义利用继承改进对方法进一步改进利用虚函数进行改进利…

设计模式结合场景(1)——支付场景(策略+工厂+模板)

ps&#xff1a;以下示例仅供参考&#xff0c;设计模式只是一种思想&#xff0c;至于怎么千变万化就看大家了。 一、背景 面试官&#xff1a;你们项目的支付场景用了哪些设计模式&#xff0c;为什么要这么做&#xff1f; 二、方案 使用策略模式定义不同支付方式的具体支付策略&…

[深度学习实战]基于PyTorch的深度学习实战(上)[变量、求导、损失函数、优化器]

目录 一、前言二、深度学习框架——PyTorch2.1 PyTorch介绍2.2 Python安装详解2.3 PyTorch安装详解 三、变量四、求导五、损失函数5.1 nn.L1Loss5.2 nn.SmoothL1Loss5.3 nn.MSELoss5.4 nn.BCELoss5.5 nn.CrossEntropyLoss5.6 nn.NLLLoss5.7 nn.NLLLoss2d 六、优化器Optim 6.1 …

ARM Coresight 系列文章 8 - ARM Coresight 通过 APBIC 级联使用

文章目录 APBIC 回顾APBIC 级联 上篇文章&#xff1a;ARM Coresight 系列文章 7 - ARM Coresight 通过 AHB-AP 访问 异构 cpu 内部 coresight 组件 APBIC 回顾 APBIC 可以连接一个或者多个APB BUS masters&#xff0c; 例如连接一个 APB-AP 组件和带有 APB 接口的 Processor&…

Java源码规则引擎:jvs-rules数据扩展及函数配置说明

jvs-rules数据拓展节点 数据拓展是数据可视化加工过程中的重要工具&#xff0c;它核心的作用是对原有数据表进行加工扩展&#xff0c;实现功能如下图所示 函数配置操作过程 操作说明 1、拖动数据拓展字段&#xff0c;并将字段拓展与之前的历史节点连接起来&#xff0c;点击数…