当前位置: 首页 > news >正文

设计模式之门面模式

前言

什么是门面模式

门面模式是一种结构型设计模式,它提供了一个统一的接口,用来访问子系统中的一群接口。它定义了一个高层接口,让子系统更容易使用。这种模式常用于将一个复杂的子系统封装成一个简单的接口,使得客户端可以方便地使用子系统的功能,而不需要了解子系统的具体实现细节。

门面模式的特点

  1. 代理模式能够隐藏真实对象的实现细节,使客户端无需知晓真实对象的工作方式和结构。
  2. 通过代理类来间接访问真实类,可以在不修改真实类的情况下对其进行扩展、优化或添加安全措施。
  3. 代理模式实现起来简单,易于扩展和维护,符合面向对象设计原则中的开闭原则。

门面模式的核心角色

门面模式(Facade Pattern)有三个核心角色:

  1. 门面角色(Facade):这是门面模式的核心,被客户角色调用。它熟悉子系统的功能,内部根据客户角色已有的需求预定了几种功能组合。
  2. 子系统角色(Subsystem):实现了子系统的功能。对于子系统角色来说,门面角色和客户角色都是未知的,它没有任何门面角色信息和链接。
  3. 客户角色(Client):这是使用门面模式的外部请求者,它通过门面角色来访问子系统,以获取所需的功能。

门面模式如何实现

假如用门面模式来模拟实现一下去饭店点菜吃饭应该怎么实现呢?虽然去饭店吃饭这件事挺普通的,但是要想吃到饭,起码是要走这样一个流程:点餐、炒菜、上菜、收/付钱。其实这里的饭店就可以看作是一个门面角色,饭店内不同的角色:如老板、收银员、服务员、厨师等,可以看作是饭店这个门面内的子系统角色,不同的角色职责是不同的,服务员负责帮客人点餐、上菜,厨师炒菜,收银员负责收钱,但是对于客人而言,吃饭是重点,通常不会关注是谁做的、谁端上来的。

那使用门面模式怎么实现呢?UML类图如下:

1、Restaurant:饭店类,有三个List类型的属性,分别用来表示饭店内会有厨师、服务员、收银员等不同角色的人员对象;对应还有三个可以给饭店增加三种不同角色人员的方法;最后一个方法就是饭店对外的主要职能:可以吃饭;

2、Waiter:服务员类,有两个方法:帮客人下单、上菜;

3、Cook:厨师类,有一个方法:炒菜;

4、Cashier:收银员类,有一个方法:收菜;

5、Cilent:客户端类,作为客户端,直接依赖Restaurant类,而不具体去找某个服务员或厨师;

/*** 服务员*/
@Data
@AllArgsConstructor
public class Waiter {private String name;public void placeOrder(){System.out.println(this.name+"->帮客人点菜");}public void serveDishes(){System.out.println(this.name+"->给客人上菜");}
}
/*** 厨师*/
@Data
@AllArgsConstructor
public class Cook {private String name;public void cooking() {System.out.println(this.name + "->炒菜");}
}
/*** 收银员*/
@Data
@AllArgsConstructor
public class Cashier {private String name;public void collectMoney() {System.out.println(this.name + "->收钱");}
}
/*** 饭店*/@Data
public class Restaurant {private String name;private List<Cook> cooks = new ArrayList<>();private List<Waiter> waiters = new ArrayList<>();private List<Cashier> cashiers = new ArrayList<>();public Restaurant(String name) {this.name = name;}public void addCooks(Cook cook) {this.cooks.add(cook);}public void addWaiter(Waiter waiter) {this.waiters.add(waiter);}public void addCashier(Cashier cashier) {this.cashiers.add(cashier);}private int ranomInt(Integer maxInt){Random random = new Random();return random.nextInt(maxInt);}public void eat(){this.waiters.get(this.ranomInt(this.waiters.size())).placeOrder();//点菜this.cooks.get(this.ranomInt(this.cooks.size())).cooking();//炒菜this.waiters.get(this.ranomInt(this.waiters.size())).serveDishes();//上菜System.out.println("客人->吃饭");this.cashiers.get(this.ranomInt(this.cashiers.size())).collectMoney();//收钱}
}
public class Client {public static void main(String[] args) {Restaurant restaurant = new Restaurant("和平饭店");Cook cook1 = new Cook("张厨师");Cook cook2 = new Cook("李厨师");restaurant.addCooks(cook1);restaurant.addCooks(cook2);Waiter waiter1 = new Waiter("王小红");Waiter waiter2 = new Waiter("张小月");restaurant.addWaiter(waiter1);restaurant.addWaiter(waiter2);Cashier cashier1 = new Cashier("老板");Cashier cashier2 = new Cashier("老板娘");restaurant.addCashier(cashier1);restaurant.addCashier(cashier2);restaurant.eat();}
}

门面模式的适用场景

门面模式适用于以下场景:

  1. 为一个复杂的子系统提供一个简单的接口,使得客户端可以方便地使用子系统的功能。
  2. 需要对一个子系统进行封装,并隐藏子系统的内部实现细节,只提供一个精简的接口供客户端使用,这样可以降低客户端与子系统的耦合度。
  3. 需要提高子系统的独立性,使得客户端不直接与子系统交互,而是通过门面角色来进行交互。
  4. 需要隔离客户端与子系统的直接交互,预防低水平人员带来的风险扩散。

总结

优点:

  1. 减少系统的相互依赖:门面模式可以让客户端只需要依赖门面对象,而与子系统无关。这样可以降低系统耦合度。
  2. 提高灵活性:通过门面角色,客户端不再直接与子系统交互,而是通过门面角色提供的精简接口来实现交互。这样,子系统的内部实现细节可以被隐藏起来,子系统如何变化对客户端来说是透明的,提高了系统的灵活性。
  3. 提高安全性:外部只能通过门面访问子系统的功能,门面没有开放的就不能访问,提高了子系统的安全性。

缺点:

  1. 不符合开闭原则。系统投产后,一旦发现错误,只能修改门面角色的代码,风险比较大。
  2. 系统的复杂性和理解难度有一定增加;

总的来说,门面模式可以简化复杂子系统的使用、隐藏实现细节、提高子系统独立性和隔离客户端与子系统的直接交互,但也存在一些缺点需要注意。在具体使用时,需要根据具体情况进行权衡,并考虑是否适合使用该模式。

相关文章:

设计模式之门面模式

前言 什么是门面模式 门面模式是一种结构型设计模式&#xff0c;它提供了一个统一的接口&#xff0c;用来访问子系统中的一群接口。它定义了一个高层接口&#xff0c;让子系统更容易使用。这种模式常用于将一个复杂的子系统封装成一个简单的接口&#xff0c;使得客户端可以方…...

Postman的使用

Postman的使用 Postman断言Postman常用断言1、断言响应状态码2、断言包含某个字符串3、断言JSON数据4、Postman断言工作原理 Postman关联Postman自动关联创建环境 3、Postman参数化CSV文件JSON文件1、用例集的导入导出2、环境导出 Postman断言 让Postman工具代替人自动判断预期…...

QGIS008:QGIS拓扑检查、修改及验证

摘要&#xff1a;本文介绍使用QGIS拓扑检查器和几何图形检查器检查图层的拓扑错误&#xff0c;修改拓扑错误&#xff0c;并对修改后的图层进行错误验证。 实验数据&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1Vy2s-KYS-XJevqHNdavv9A?pwdf06o 提取码&#xff1a…...

安装DBD-Oracle报错处理

cd DBD-Oracle-1.83 perl Makefile.PL make && make install make编译报错如下&#xff1a; /bin/ld: 找不到 -lnsl collect2: 错误&#xff1a;ld 返回 1 make: *** [Makefile:524&#xff1a;blib/arch/auto/DBD/Oracle/Oracle.so] 错误 1 [rootlocalhost DBD-Ora…...

【机器学习】KNN算法-鸢尾花种类预测

KNN算法-鸢尾花种类预测 文章目录 KNN算法-鸢尾花种类预测1. 数据集介绍2. KNN优缺点&#xff1a; K最近邻&#xff08;K-Nearest Neighbors&#xff0c;KNN&#xff09;算法是一种用于模式识别和分类的简单但强大的机器学习算法。它的工作原理非常直观&#xff1a;给定一个新数…...

LuatOS-SOC接口文档(air780E)--lora - lora驱动模块

常量 常量 类型 解释 lora.SLEEP number SLEEP模式 lora.STANDBY number STANDBY模式 lora.init(ic, loraconfig,spiconfig) lora初始化 参数 传入值类型 解释 string lora 型号&#xff0c;当前支持&#xff1a; llcc68 sx1268 table lora配置参数,与具体设备…...

Compose 自定义 - 绘制 Draw

一、概念 所有的绘制操作都是通过调整像素大小来执行的。若要确保项目在不同的设备密度和屏幕尺寸上都能采用一致的尺寸&#xff0c;请务必使用 .toPx() 对 dp 进行转换或者采用小数尺寸。 二、Modifier 修饰符绘制 官方页面 在修饰的可组合项之上或之下绘制。 .drawWithCon…...

c#学习相关系列之构造函数

目录 一、构造函数的作用 二、构造函数的特征 三、三种构造函数介绍 1、实例构造函数 2、静态构造函数 3、私有构造函数 一、构造函数的作用 构造函数用来创建对象&#xff0c;并且可以在构造函数中对此对象进行初始化。构造函数具有与类相同的名称&#xff0c;它通常用来…...

CS224W1.3——图表示的选择

文章目录 1. 图网络构成2. 选择一个合适的表示3. 图结构实例3.1 二部图3.2 图的表示 4. 节点和边的属性 这小节主要讲图表示的选择。 1. 图网络构成 对于每个实体&#xff0c;我们创建节点 N N N&#xff0c;对于每个关系&#xff0c;我们创建边 E E E&#xff0c;对于整体而言…...

rust学习——插件rust-analyzer安装与配置

插件rust-analyzer安装与配置 rust-analyzer有一个中文版本。安装前请先卸载其他rust插件。 首次安装会下载语言服务。 您可能是首次安装Rust中文标准库插件 现在还需要安装Rust语言服务(约25MB单文件)就全部安装完成啦~正在后台自动安装请稍后... 下载完成...OK配置 "…...

Spring Boot简介

Spring Boot帮助你创建可以运行的独立的、基于Spring的生产级应用程序。 我们对Spring平台和第三方库采取了有主见的观点&#xff0c;这样你就能以最少的麻烦开始工作。 大多数Spring Boot应用程序只需要很少的Spring配置。 你可以使用Spring Boot来创建Java应用程序&#xff…...

Linux下protobuf和 protobuf-c安装使用

如果在 C语言中使用 protobuf&#xff0c;就需要使用 protobuf-c这个库。 protobuf使用详解&#xff1a;https://blog.csdn.net/qq_42402854/article/details/134066566 下面在 Linux下安装 protobuf和 protobuf-c。 一、下载 protobuf和 protobuf-c 官方的 Protocol Buffer提…...

FastAPI 快速学习之 Flask 框架对比

目录 一、前言二、FastAPI 优势三、Hello World四、HTTP 方法五、URL 变量六、查询字符串七、POST 请求八、文件上传九、表单提交十、Cookies十一、模块化视图十二、数据校验十三、自动化文档Swagger 风格ReDoc 风格 十四、CORS跨域 一、前言 本文主要对 FastAPI 与 Flask 框架…...

Spring Boot和XXL-Job:高效定时任务管理

Spring Boot和XXL-Job&#xff1a;高效定时任务管理 前言第一&#xff1a;XXL-Job简介什么是XXL-job对比别的任务调度 第二&#xff1a; springboot整合XXL-job配置XXL-Job Admin拉取XXL-Job代码修改拉取的配置 配置执行器自己的项目如何整合maven依赖properties文件配置执行器…...

3、QtCharts 动态曲线图

文章目录 效果声明变量构建静态图表创建计时器连接信号与槽槽函数核心代码 效果 声明变量 构建静态图表 //构建曲线系列m_splineSerisenew QSplineSeries(this);//为折线添加数据qreal x0.f;for (size_t i0;i<c_MaxSize;i){xqreal(i1)/c_MaxSize;m_splineSerise->append(…...

Linux下自动挂载U盘或者USB移动硬盘

最近在折腾用树莓派&#xff08;实际上是平替香橙派orangepi zero3&#xff09;搭建共享文件服务器&#xff0c;有一个问题很重要&#xff0c;如何在系统启动时自动挂载USB移动硬盘。 1 使用/etc/fstab 最开始尝试了用/etc/fstab文件下增加:"/dev/sda1 /home/orangepi/s…...

一文通透位置编码:从标准位置编码到旋转位置编码RoPE

前言 关于位置编码和RoPE 我之前在本博客中的另外两篇文章中有阐述过(一篇是关于LLaMA解读的&#xff0c;一篇是关于transformer从零实现的)&#xff0c;但自觉写的不是特别透彻好懂再后来在我参与主讲的类ChatGPT微调实战课中也有讲过&#xff0c;但有些学员依然反馈RoPE不是…...

八皇后问题

1、问题描述 在棋盘上放置 8 个皇后&#xff0c;使得它们互不攻击&#xff0c;此时每个皇后的攻击范围为同行同列和同对角线&#xff0c;要求找出所有解&#xff0c;如下图所示。 左图为皇后的攻击范围&#xff0c;右图为一个可行解。 2、分析 最简单的思路是把问题转化为 “…...

UE4/UE5 设置widget中text的字体Outline

想要在蓝图中控制Widget 中的 text字体&#xff0c;对字体outline参数进行设置。 但是蓝图中无法直接获取设置outline参数的方法&#xff1a; 没有outline相关的蓝图函数 该参数本身是在Font类别下的扩展&#xff0c;所以只要获取设置Font参数即可进行outline的设置 text连出…...

漏洞复现-phpmyadmin_SQL注入 (CVE-2020-5504)

phpmyadmin SQL注入 _&#xff08;CVE-2020-5504&#xff09; 漏洞信息 CVE-2020-5504sql注入漏洞Phpmyadmin 5.00以下 描述 ​ phpMyAdmin是Phpmyadmin团队的一套免费的、基于Web的MySQL数据库管理工具。该工具能够创建和删除数据库&#xff0c;创建、删除、修改数据库表&…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上&#xff0c;你可以使用apt包管理器来安装NFS服务器。打开终端并运行&#xff1a; sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享&#xff0c;例如/shared&#xff1a; sudo mkdir /shared sud…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

springboot整合VUE之在线教育管理系统简介

可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生&#xff0c;小白用户&#xff0c;想学习知识的 有点基础&#xff0c;想要通过项…...

Java编程之桥接模式

定义 桥接模式&#xff08;Bridge Pattern&#xff09;属于结构型设计模式&#xff0c;它的核心意图是将抽象部分与实现部分分离&#xff0c;使它们可以独立地变化。这种模式通过组合关系来替代继承关系&#xff0c;从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

【C++进阶篇】智能指针

C内存管理终极指南&#xff1a;智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...