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

外观模式简介

概念

外观模式(Facade Pattern)是一种结构型设计模式,它提供了一个统一的接口,用于访问子系统中的一组接口。外观模式隐藏了子系统的复杂性,并将其封装在一个简单易用的接口中,使得客户端可以更方便地使用子系统。

特点

  1. 提供了一个简化和统一的接口,隐藏了底层子系统的复杂性。
  2. 将客户端与子系统之间解耦,降低了客户端代码与子系统之间的直接依赖关系。
  3. 通过外观类来集中管理和协调多个相关对象,提高了代码可维护性和灵活性。

优点

  1. 简化客户端与复杂子系统之间的交互过程。
  2. 隐藏底层实现细节,提高代码可读性和可维护性。
  3. 降低耦合度,减少对其他代码影响。

缺点

  1. 如果需要修改或扩展功能,则可能需要修改外观类本身。
  2. 外观类承担较多职责时会变得臃肿。

适用场景

  1. 当存在一个复杂数量较大且关联紧密的类库时,可以使用外观模式将其封装成一个简单易用、统一的接口。
  2. 当需要简化一个复杂子系统的接口,并提供一个更高层次的接口供客户端使用时,可以使用外观模式。

实现方式

单一外观类

实现原理

  1. 定义一个外观类,该类包含对子系统的引用。
  2. 在外观类中定义方法,每个方法代表一个功能或操作。在方法内部调用相应子系统的方法来完成具体逻辑。
  3. 客户端通过直接调用外观类的方法来使用子系统。

实现代码

// 子系统A
class SubSystemA {public void operationA() {System.out.println("SubSystemA operation");}
}// 子系统B
class SubSystemB {public void operationB() {System.out.println("SubSystemB operation");}
}// 外观类
class Facade {private SubSystemA subSystemA;private SubSystemB subSystemB;public Facade() {this.subSystemA = new SubSystemA();this.subSystemB = new SubSystemB();}public void operation() {subSystemA.operationA();subSystemB.operationB();}
}public class Main {public static void main(String[] args) {Facade facade = new Facade(); // 创建外观类对象facade.operation(); // 调用外观类的方法,实现对子系统的操作}
}

在上述示例中,SubSystemASubSystemB分别代表两个子系统。Facade是单一外观类,封装了对这两个子系统的引用,并提供了一个名为operation()的方法来调用这两个子系统的具体操作。客户端通过创建一个外观数对象,并调用其方法来使用子系统。在此示例中,客户端只需要与外观类进行交互,而无需直接与子系统进行交互。

存在问题:
 

  1. 如果有多个不同类型的客户端需要访问不同功能集合,则可能需要修改和扩展单一外观类。
  2. 单一外观类承担了较多职责,导致代码变得庞大而复杂。

多个外观类

实现原理

  1. 定义多个外观类,每个外观类分别与一个或多个子系统相关联。
  2. 在每个外观类中定义方法,每个方法代表一个功能或操作。在方法内部调用相应子系统的方法来完成具体逻辑。
  3. 客户端根据需要选择合适的外观数进行调用。

实现代码

// 子系统A
class SubSystemA {public void operationA() {System.out.println("SubSystemA operation");}
}// 子系统B
class SubSystemB {public void operationB() {System.out.println("SubSystemB operation");}
}// 外观类
class Facade1 {private SubSystemA subSystemA;public Facade1() {this.subSystemA = new SubSystemA();}public void operation() {subSystemA.operationA();}
}// 另一个外观类
class Facade2 {private SubSystemB subSystemB;public Facade2() {this.subSystemB = new SubSystemB();}public void operation() {subSystemB.operationB();}
}public class Main {public static void main(String[] args) {Facade1 facade1 = new Facade1(); // 创建外观数对象1Facade2 facade2 = new Facade2(); // 创建外观数对象2facade1.operation(); // 调用外观数对象1的方法,实现对子系统A的操作facade2.operation(); // 调用外观数对象2的方法,实现对子系统B的操作}
}

在上述示例中,SubSystemASubSystemB分别代表两个不同的子系统。Facade1Facade2是两个独立的外观类,分别封装了对这两个子系统的引用,并提供了一个名为 operation() 的方法来调用相应子系统的具体操作。客户端根据需要选择合适的外观类进行调用。在此示例中,客户端可以选择使用 Facade1  Facade2 来访问特定子系统。这样客户端只需要与所选外观类进行交互,而无需直接与各个子系统进行交互。

嵌套调用

实现原理

  1. 定义多个外观类,每个外观类负责封装和管理特定子系统的操作。
  2. 在一个外观类的操作方法内部,通过创建其他外观类对象并调用其相应的方法来实现嵌套调用。
  3. 客户端只需要与最上层的外观数进行交互,无需关心底层具体子系统。

实现代码

        

// 子系统A
class SubSystemA {public void operationA() {System.out.println("SubSystemA operation");}
}// 子系统B
class SubSystemB {public void operationB() {System.out.println("SubSystemB operation");}
}// 外观类
class Facade1 {private SubSystemA subSystemA;private Facade2 facade2;public Facade1() {this.subSystemA = new SubSystemA();this.facade2 = new Facade2();}public void operation() {subSystemA.operationA();facade2.operation(); // 嵌套调用Facade2的操作方法}
}// 另一个外观类
class Facade2 {private SubSystemB subSystemB;public Facade2() {this.subSystemB = new SubSystemB();}public void operation() {subSystemB.operationB();}
}public class Main {public static void main(String[] args) {Facade1 facade1 = new Facade1(); // 创建外观类对象facade1.operation(); // 调用外观类对象的方法,实现对子系统A和子系统B的嵌套调用}
}

在上述示例中,SubSystemASubSystemB分别代表两个不同的子系统。Facade1是一个外观类,封装了对这两个子系统的引用,并提供了一个名为 operation() 的方法来调用相应子系统的具体操作。在 operation() 方法内部,除了调用 subsystemA.operationA() 外,还创建并使用了 Facade2 对象,并通过其 operation() 方法实现对另一个子系统 B 的操作。

客户端只需要与最上层的外观数进行交互,即调用 facade1.operation() 方法。这样客户端无需关心底层具体子系统及其嵌套调用逻辑,通过外观类的嵌套调用,实现了对多个子系统的操作。

存在问题:

  1. 嵌套过深可能导致代码可读性降低和维护困难。
  2. 如果有新的子系统加入或旧的子系统变更,需要修改和扩展相应的嵌套逻辑。

相关文章:

外观模式简介

概念: 外观模式(Facade Pattern)是一种结构型设计模式,它提供了一个统一的接口,用于访问子系统中的一组接口。外观模式隐藏了子系统的复杂性,并将其封装在一个简单易用的接口中,使得客户端可以…...

web pdf 拖拽签章

web pdf 拖拽签章 主要通过火狐的pdfjs 来实现 1. 下载js 并编译 地址 https://mozilla.github.io/pdf.js/ 按照官网当下下载并编译就得到了js 2.其实也没有什么好讲的,都是用的js中的方法,官网中都有 按照步骤就能生成一个document元素,然…...

SQLAlchemy 库创建数据库引擎和会话工厂附带SQLSERVER驱动版本确认方式

SQLAlchemy 库创建数据库引擎和会话工厂 from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker# 创建数据库引擎 engine create_engine(mssqlpyodbc://user:passhost:port/database?driverODBCDriver11forSQLServer)# 创建会话工厂 Session sess…...

用Python登录账户

1 问题 如何利用python登录账户? 2 方法 账户和密码存放在文件夹中从文件夹中读取并比较密码密文验证三次后,如不成功则锁定用户 通过。。。。。。。。等证明提出的方法是有效的,能够解决开头提出的问题。 代码清单 1 import osimport getpas…...

梳理下我自已对Reactor与及IO多路复用的select\poll\epoll的理解

Reactor是一种设计思想的落地,其中IO多路复用的具体落地:select\poll\epoll。都是基于Reactor的延伸。它的核心是Reactor与资源处理器。Reactor负责监听与事件的分发,事件包括连接事件、读事件、写事件。 具体的流程是系统调用监听请求&…...

4. 广播变量

一、分区规则(DataStream Broadcast)和广播变量(Flink Broadcast) 1.1 DataStream Broadcast(分区规则) ​ 分区规则是把元素广播给所有的分区,数据会被重复处理。 DataStream.broadcast()1.…...

GPT 内部 — I : 了解文本生成

年轻的陀思妥耶夫斯基被介绍给生成AI,通过Midjourney创建 一、说明 我经常与不同领域的同事互动,我喜欢向几乎没有数据科学背景的人传达机器学习概念的挑战。在这里,我试图用简单的术语解释 GPT 是如何连接的,只是这次是书面形式。…...

平板触控笔哪款好用?好用的第三方apple pencil

而对于那些把ipad当做学习工具的人而言,苹果Pencil就成了必备品。但因为苹果Pencil太贵了,不少的学生们买不起。因此,最佳的选择还是平替电容笔,今天在这里整理了一些高性价比的电容笔! 一、挑选电容笔的要点&#xf…...

Mac 上更新系统PATH环境变量

目录 为什么要更新系统的PATH环境变量如何更新系统的PATH环境变量1. 确保你知道工具的实际安装位置。2. 将目录(实际安装位置)添加到PATH:export PATH$PATH:/path/to/your/tools补充:通过以下方法来确定当前正在使用的是Bash还是Z…...

Visual Studio Code 终端配置使用 MySQL

Visual Studio Code 终端配置使用 MySQL 找到 MySQL 的 bin 目录 在导航栏中搜索–》服务 找到MySQL–>双击 在终端切换上面找到的bin目录下输入指令 终端为Git Bash 输入命令 ./mysql -u root -p 接着输入密码,成功在终端使用 MySQL 数据库。...

12 | 使用 Spark SQL执行CURL

Spark SQL 是 Apache Spark 生态系统中的一个组件,它提供了用于结构化数据处理和分析的高级接口。Spark SQL 可以让用户使用 SQL 语言来查询和操作数据,同时也提供了强大的分布式计算能力。下面是关于 Spark SQL、SparkSession 和 DataFrame 的关键点: 1. Spark SQL: 定义…...

容器编排学习(七)控制器介绍与使用

一 控制器 控制器是 k8s内置的管理工具。可以帮助用户实现 Pod的自动部署、自维护、扩容、滚动更新等功能的自动化程序。 为什么要使用控制器? 有大量的 Pod需要维护管理需要维护 Pod的健康状态控制器可以像机器人一样可以替用户完成维护管理的工作 二 Deployment 1 概…...

一文看懂微信小程序新版隐私协议(附带弹窗组件)

一、前言 微信小程序近期又迎来了一次改革–9月15日之后如果小程序涉及调用微信的隐私接口获取用户的信息的,需要用户手动同意协议后才可正常调用接口,否则会返回报错信息。 隐私接口目前常用的有:手机号快捷获取、读取照片、获取用户的头像…...

Java认识异常(超级详细)

目录 异常的概念和体系结构 异常的概念 异常的体系结构 异常的分类 1.编译时异常 2.运行时异常 异常的处理 防御式编程 LBYL EAFP 异常的抛出 异常的捕获 异常声明throws try-catch捕获并处理 finally 异常的处理流程 异常的概念和体系结构 异常的概念 在Java中…...

危险边缘:揭示 Python 编程中易被忽视的四个安全陷阱

今天我们将要谈论一个非常重要的话题:Python 编程中的安全问题。作为一门广受欢迎的编程语言,Python 已经成为了许多开发者、计算机专业学生以及打工人的必备技能。 原文链接食用更佳 危险边缘:揭示 Python 编程中易被忽视的四个安全问题 然…...

抖店开通后,新手必须要知道的几个做店技巧,建议认真看完

我是王路飞。 抖店的运营,无非就是围绕【产品】【流量】展开的。 你要是能把这两个点给搞明白,新店快速出单、真是爆单就不再是问题了。 今天就给你们说一下,抖店开通后,作为一个新手商家,你必须要知道的几个做店技…...

FPGA时序分析与约束(5)——时序路径

一、前言 在之前的文章中我们分别介绍了组合电路的时序,时序电路的时序和时钟的时序问题,我们也对于时序分析,时序约束和时序收敛几个基本概念进行了区分,在这篇文章中,我们将介绍时序约束相关的最后一部分基本概念&am…...

Flutter:构建跨平台应用的未来选择

随着移动设备的普及和技术的不断发展,跨平台移动应用开发成为了一个热门的需求。Flutter作为一款由Google开发的开源移动应用开发框架,受到了越来越多的关注。本文将带你了解Flutter的优势、应用场景以及如何使用Flutter进行开发。 一、Flutter的优势 …...

08_瑞萨GUI(LVGL)移植实战教程之LVGL对接串口打印

本系列教程配套出有视频教程,观看地址:https://www.bilibili.com/video/BV1gV4y1e7Sg 8. LVGL对接串口打印 本次实验我们为LVGL库对接串口的打印功能。 8.1 复制工程 上次实验得出的工程我们可以通过复制在原有的基础上得到一个新的工程。 如果你不清…...

【LeetCode75】第五十题 无限集中的最小数字

目录 题目: 示例: 分析: 代码: 题目: 示例: 分析: 这是我们在LeetCode75里遇到的第二道设计类题目,难度比上一次的设计题目要难上一些。 题目假设我们拥有一个从1开始的无限集…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

idea大量爆红问题解决

问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...

大数据学习(132)-HIve数据分析

​​​​🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言&#x1f4…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...

windows系统MySQL安装文档

概览:本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容,为学习者提供全面的操作指导。关键要点包括: 解压 :下载完成后解压压缩包,得到MySQL 8.…...

土建施工员考试:建筑施工技术重点知识有哪些?

《管理实务》是土建施工员考试中侧重实操应用与管理能力的科目,核心考查施工组织、质量安全、进度成本等现场管理要点。以下是结合考试大纲与高频考点整理的重点内容,附学习方向和应试技巧: 一、施工组织与进度管理 核心目标: 规…...