外观模式简介
概念:
外观模式(Facade Pattern)是一种结构型设计模式,它提供了一个统一的接口,用于访问子系统中的一组接口。外观模式隐藏了子系统的复杂性,并将其封装在一个简单易用的接口中,使得客户端可以更方便地使用子系统。
特点:
- 提供了一个简化和统一的接口,隐藏了底层子系统的复杂性。
- 将客户端与子系统之间解耦,降低了客户端代码与子系统之间的直接依赖关系。
- 通过外观类来集中管理和协调多个相关对象,提高了代码可维护性和灵活性。
优点:
- 简化客户端与复杂子系统之间的交互过程。
- 隐藏底层实现细节,提高代码可读性和可维护性。
- 降低耦合度,减少对其他代码影响。
缺点:
- 如果需要修改或扩展功能,则可能需要修改外观类本身。
- 外观类承担较多职责时会变得臃肿。
适用场景:
- 当存在一个复杂数量较大且关联紧密的类库时,可以使用外观模式将其封装成一个简单易用、统一的接口。
- 当需要简化一个复杂子系统的接口,并提供一个更高层次的接口供客户端使用时,可以使用外观模式。
实现方式:
单一外观类
实现原理
- 定义一个外观类,该类包含对子系统的引用。
- 在外观类中定义方法,每个方法代表一个功能或操作。在方法内部调用相应子系统的方法来完成具体逻辑。
- 客户端通过直接调用外观类的方法来使用子系统。
实现代码
// 子系统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(); // 调用外观类的方法,实现对子系统的操作}
}
在上述示例中,SubSystemA和SubSystemB分别代表两个子系统。Facade是单一外观类,封装了对这两个子系统的引用,并提供了一个名为operation()的方法来调用这两个子系统的具体操作。客户端通过创建一个外观数对象,并调用其方法来使用子系统。在此示例中,客户端只需要与外观类进行交互,而无需直接与子系统进行交互。
存在问题:
- 如果有多个不同类型的客户端需要访问不同功能集合,则可能需要修改和扩展单一外观类。
- 单一外观类承担了较多职责,导致代码变得庞大而复杂。
多个外观类
实现原理
- 定义多个外观类,每个外观类分别与一个或多个子系统相关联。
- 在每个外观类中定义方法,每个方法代表一个功能或操作。在方法内部调用相应子系统的方法来完成具体逻辑。
- 客户端根据需要选择合适的外观数进行调用。
实现代码
// 子系统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的操作}
}
在上述示例中,SubSystemA和SubSystemB分别代表两个不同的子系统。Facade1和Facade2是两个独立的外观类,分别封装了对这两个子系统的引用,并提供了一个名为 operation() 的方法来调用相应子系统的具体操作。客户端根据需要选择合适的外观类进行调用。在此示例中,客户端可以选择使用 Facade1 或 Facade2 来访问特定子系统。这样客户端只需要与所选外观类进行交互,而无需直接与各个子系统进行交互。
嵌套调用
实现原理
- 定义多个外观类,每个外观类负责封装和管理特定子系统的操作。
- 在一个外观类的操作方法内部,通过创建其他外观类对象并调用其相应的方法来实现嵌套调用。
- 客户端只需要与最上层的外观数进行交互,无需关心底层具体子系统。
实现代码
// 子系统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的嵌套调用}
}
在上述示例中,SubSystemA和SubSystemB分别代表两个不同的子系统。Facade1是一个外观类,封装了对这两个子系统的引用,并提供了一个名为 operation() 的方法来调用相应子系统的具体操作。在 operation() 方法内部,除了调用 subsystemA.operationA() 外,还创建并使用了 Facade2 对象,并通过其 operation() 方法实现对另一个子系统 B 的操作。
客户端只需要与最上层的外观数进行交互,即调用 facade1.operation() 方法。这样客户端无需关心底层具体子系统及其嵌套调用逻辑,通过外观类的嵌套调用,实现了对多个子系统的操作。
存在问题:
- 嵌套过深可能导致代码可读性降低和维护困难。
- 如果有新的子系统加入或旧的子系统变更,需要修改和扩展相应的嵌套逻辑。
相关文章:
外观模式简介
概念: 外观模式(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太贵了,不少的学生们买不起。因此,最佳的选择还是平替电容笔,今天在这里整理了一些高性价比的电容笔! 一、挑选电容笔的要点…...
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开始的无限集…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...
解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用
在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...
Ubuntu Cursor升级成v1.0
0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开,快捷键也不好用,当看到 Cursor 升级后,还是蛮高兴的 1. 下载 Cursor 下载地址:https://www.cursor.com/cn/downloads 点击下载 Linux (x64) ,…...
深入浅出Diffusion模型:从原理到实践的全方位教程
I. 引言:生成式AI的黎明 – Diffusion模型是什么? 近年来,生成式人工智能(Generative AI)领域取得了爆炸性的进展,模型能够根据简单的文本提示创作出逼真的图像、连贯的文本,乃至更多令人惊叹的…...
协议转换利器,profinet转ethercat网关的两大派系,各有千秋
随着工业以太网的发展,其高效、便捷、协议开放、易于冗余等诸多优点,被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口,具有实时性、开放性,使用TCP/IP和IT标准,符合基于工业以太网的…...
解析两阶段提交与三阶段提交的核心差异及MySQL实现方案
引言 在分布式系统的事务处理中,如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议(2PC)通过准备阶段与提交阶段的协调机制,以同步决策模式确保事务原子性。其改进版本三阶段提交协议(3PC…...
2025年- H71-Lc179--39.组合总和(回溯,组合)--Java版
1.题目描述 2.思路 当前的元素可以重复使用。 (1)确定回溯算法函数的参数和返回值(一般是void类型) (2)因为是用递归实现的,所以我们要确定终止条件 (3)单层搜索逻辑 二…...
