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

外观模式的理解和实践

        外观模式(Facade Pattern)是一种常用的软件设计模式,它提供了一个统一的接口,用来访问子系统中的一群接口。该模式定义了一个高层的接口,使得子系统更容易使用。简单来说,外观模式就是通过引入一个外观角色来简化客户端与子系统之间的交互,为复杂的子系统调用提供一个统一的入口,降低子系统与客户端的耦合度,且客户端调用更加方便。

一、外观模式的理解

        外观模式属于结构型设计模式,其核心思想是通过引入一个新的外观角色来降低原有系统的复杂度,同时降低客户类与子系统的耦合度。这一模式又称为门面模式,它将复杂的子系统封装成一个简单的高层接口,从而方便客户的使用。

        外观模式在迪米特法则(Demeter's Law)中有所体现,即一个对象应该对其他对象有最少的了解。通过外观模式,客户端只需要与外观对象进行交互,而不需要了解子系统的内部结构,从而实现系统的松耦合。

        具体来说,外观模式的作用主要体现在以下几个方面:

  1. 简化客户端调用:通过提供一个统一的接口,使得客户端能够更加方便地调用子系统的功能,而不需要关心子系统的具体实现。
  2. 降低系统耦合度:客户端与子系统之间的耦合度降低,减少了客户端对子系统内部变化的依赖,提高了系统的可维护性。
  3. 优化用户体验:外观模式将复杂的流程简化,优化了用户体验,同时方便系统的扩展与修改。

        例如,一个餐厅的点餐系统就是一个典型的外观模式的应用。顾客不需要了解厨房的具体操作,只需通过点餐系统选择餐食,然后支付费用,等待片刻即可得到美食。在这个过程中,点餐系统就起到了外观角色的作用,简化了顾客的点餐流程。

二、外观模式的实践

        以下将通过Java代码示例来展示外观模式的实现。

1. 子系统组件的定义

        首先,我们需要定义几个子系统组件,这些组件提供了一些具体的方法,用于完成不同的功能。

// 子系统组件A
public class SubSystemA {public void operationA() {System.out.println("SubSystemA performing operationA.");}
}// 子系统组件B
public class SubSystemB {public void operationB() {System.out.println("SubSystemB performing operationB.");}
}// 子系统组件C
public class SubSystemC {public void operationC() {System.out.println("SubSystemC performing operationC.");}
}


2. 外观类的定义

        接下来,我们定义一个外观类,这个类将封装对子系统组件的调用,为客户端提供一个简化的接口。

// 外观类
public class Facade {// 子系统组件的实例,可以被外观类封装和管理private SubSystemA subSystemA;private SubSystemB subSystemB;private SubSystemC subSystemC;// 构造函数,初始化子系统组件public Facade() {this.subSystemA = new SubSystemA();this.subSystemB = new SubSystemB();this.subSystemC = new SubSystemC();}// 外观方法,客户端通过这个方法访问子系统功能public void performComplexOperation() {System.out.println("Facade initiating complex operation...");subSystemA.operationA(); // 调用子系统A的方法subSystemB.operationB(); // 调用子系统B的方法subSystemC.operationC(); // 调用子系统C的方法System.out.println("Facade completed complex operation.");}
}


3. 客户端代码

        最后,我们编写客户端代码,通过外观类来访问子系统的功能。

// 客户端类,使用外观模式来访问子系统功能
public class ClientWithFacade {public static void main(String[] args) {// 创建外观类的实例Facade facade = new Facade();// 通过外观类的方法访问子系统功能facade.performComplexOperation();}
}


        运行上述客户端代码,输出结果为:

Facade initiating complex operation...
SubSystemA performing operationA.
SubSystemB performing operationB.
SubSystemC performing operationC.
Facade completed complex operation.


        从上述结果可以看出,客户端通过外观类 Facade 的 performComplexOperation 方法,成功调用了子系统组件 SubSystemASubSystemB 和 SubSystemC 的方法,完成了一个复杂的操作。而客户端代码并没有直接调用子系统组件的方法,降低了耦合度,提高了系统的可维护性。

4. 对比分析

        为了更直观地理解外观模式,我们可以对比一个未使用外观模式的示例。

// 客户端类,未使用外观模式
public class ClientWithoutFacade {public static void main(String[] args) {// 创建子系统组件实例SubSystemA subSystemA = new SubSystemA();SubSystemB subSystemB = new SubSystemB();SubSystemC subSystemC = new SubSystemC();// 客户端直接调用子系统的方法来完成某项任务subSystemA.operationA(); // 调用子系统A的方法subSystemB.operationB(); // 调用子系统B的方法subSystemC.operationC(); // 调用子系统C的方法// 输出结果表示任务完成System.out.println("Task is completed without Facade Pattern.");}
}


        运行上述客户端代码,输出结果为:

SubSystemA performing operationA.
SubSystemB performing operationB.
SubSystemC performing operationC.
Task is completed without Facade Pattern.


        虽然这个代码也能正确运行并完成任务,但它存在一些问题:

  1. 客户端代码与子系统紧密耦合:客户端代码必须了解子系统的具体实现和组成,如果子系统的内部结构发生变化,客户端代码可能需要进行大量修改。
  2. 增加了复杂性和出错的可能性:客户端代码需要处理与多个子系统组件的交互,增加了复杂性和出错的可能性。

        相比之下,使用外观模式的客户端代码更加简洁、清晰,降低了与子系统之间的耦合度,提高了系统的可维护性。

三、外观模式的优缺点

优点

  1. 简化客户端调用:通过提供一个统一的接口,使得客户端能够更加方便地调用子系统的功能。
  2. 降低系统耦合度:客户端与子系统之间的耦合度降低,减少了客户端对子系统内部变化的依赖。
  3. 提高系统的可维护性:由于系统复杂度降低,系统的可维护性得到提高。
  4. 优化用户体验:外观模式将复杂的流程简化,优化了用户体验。

缺点

  1. 增加了外观类的复杂性:外观类需要封装对多个子系统组件的调用,如果子系统组件过多或功能复杂,外观类的实现可能会变得复杂。
  2. 不易扩展:当需要增加新的子系统组件时,可能需要修改外观类,违反了开闭原则(对扩展开放,对修改关闭)。

总结

        外观模式是一种非常实用的设计模式,它通过引入一个外观角色来简化客户端与子系统之间的交互,为复杂的子系统调用提供一个统一的入口。外观模式降低了系统耦合度,提高了系统的可维护性,并优化了用户体验。在实际应用中,我们应该根据具体的需求和条件来选择是否使用外观模式,并注意其优缺点,合理设计系统的架构。

        通过以上对外观模式的理解和实践,相信读者已经能够掌握这一设计模式的核心思想和实现方法,并在实际开发中灵活运用。

相关文章:

外观模式的理解和实践

外观模式(Facade Pattern)是一种常用的软件设计模式,它提供了一个统一的接口,用来访问子系统中的一群接口。该模式定义了一个高层的接口,使得子系统更容易使用。简单来说,外观模式就是通过引入一个外观角色…...

linux离线安装部署redis

版本信息 linux版本:CentOS-7-x86_64 redis版本:redis-6.2.6 VMware:VMware-workstation-full-16.1.1 xshell: Xshell-7.0 安装 1.查看当前虚拟机ip命令:ifconfig -a 2.xhell连接虚拟机 ,在xshell页面点击文件-…...

网管平台(基础篇):路由器的介绍与管理

路由器简介 路由器(Router)是一种计算机网络设备,它的主要作用是将数据通过打包,并按照一定的路径选择算法,将网络传送至目的地。路由器能够连接两个或更多个网络,并根据信道的情况自动选择和设定路由&…...

数据结构——跳表

目录 1.什么是跳表-skiplist 2.skiplist的效率如何保证? 3.skiplist的实现 4.skiplist跟平衡搜索树和哈希表的对比 1.什么是跳表-skiplist skiplist本质上也是一种查找结构,用于解决算法中的查找问题,跟平衡搜索树和哈希表的价值是一样的…...

活动预告 |【Part2】Microsoft Azure 在线技术公开课:基础知识

课程介绍 参加“Azure 在线技术公开课:基础知识”活动,培养有助于创造新的技术可能性的技能并探索基础云概念。参加我们举办的本次免费培训活动,扩充自身的云模型和云服务类型知识。你还可以查看以计算、网络和存储为核心的 Azure 服务。 课…...

PyCharm如何导入库( 包 )

目录 1.在主界面中导库 2.用设置->项目安装库 2.1.使用右上方按钮 2.2.使用右下方Python解释器 3.使用左下角终端导库 1.在主界面中导库 在主界面输入导库后等待一会儿,会在那一行出现一个红色灯。 图1 红色灯 我们点击红色灯,会出现 图2 错误选…...

【DevOps基础篇】SCM(Source Code Management)

目录 代码管理工具Git特点:SVN特点:Git与SVN的对比:Git 的开发工作流程(flow)的设计Git Flow主要特点:工作流程:GitHub Flow主要特点:工作流程:两种Flow的对比:推荐超级课程: Docker快速入门到精通Kubernetes入门到大师通关课AWS云服务快速入门实战代码管理工具 Gi…...

DDS—RTPS一致性测试案例分析

1 往期回顾 通过《DDS数据分发服务—提升汽车领域数据传输效率》和《DDS—DCPS测试策略介绍及实际案例分析》这两篇文章的介绍,相信广大读者对Data Distribution Service(DDS)协议和Data Centric Publish Subscribe(DCPS)测试有了基本了解:DDS协议致力于…...

【深度学习入门】深度学习介绍

1.1 深度学习介绍 学习目标 目标 知道深度学习与机器学习的区别了解神经网络的结构组成知道深度学习效果特点 应用 无 区别 特征提取方面 机器学习的特征工程步骤是要靠手动完成的,而且需要大量领域专业知识深度学习通常由多个层组成,它们通常将更简…...

数值分析—非线性方程的数值解

研究背景 形如 x − t a n x 0 x-tanx0 x−tanx0、 x l n x e − x 2 s i n x 0 xlnxe^{-x^2}sinx0 xlnxe−x2sinx0等称为非线性方程,自变量之间并非简单的线性关系,这种问题我们无法通过其结构求解,需要其他的逼近方式,本章…...

LDR6500应用:C转DP线材双向投屏开启全新体验

在当今这个科技日新月异、蓬勃发展的时代,高清视频传输以及显示技术已经深深融入到我们日常生活与工作的方方面面,其重要性不言而喻。不管是在商务场合的会议演示,还是教育领域的娱乐享受,以及充满激情的游戏竞技领域,…...

路径规划之启发式算法之十六:和声搜索算法(Harmony Search, HS)

和声搜索算法(Harmony Search, HS)是一种新兴的启发式全局搜索算法,是一种模拟音乐家即兴演奏过程的群体智能优化算法。这种算法由Zong Woo Geem等人在2001年提出,灵感来源于音乐家在寻找和声时的创造性思维过程。HS算法通过模拟音乐家演奏音乐时的选择过程来寻找问题的最优…...

Redis - 实战之 全局 ID 生成器 RedisIdWorker

概述 定义:一种分布式系统下用来生成全局唯一 ID 的工具 特点 唯一性,满足优惠券需要唯一的 ID 标识用于核销高可用,随时能够生成正确的 ID高性能,生成 ID 的速度很快递增性,生成的 ID 是逐渐变大的,有利于…...

matlab 连接远程服务器

通过matlab 控制远程服务器 查看 matlab 中 python 接口脚本 对于 matlab 2010b 兼容的 最高 Python版本是 3.10 安装 3.10 版本的Python,并安装 paramiko 库 pip install paramikomatlab 中设置 Python的环境 例如 pyversion(D:/Anaconda3/python.e…...

在服务器自主选择GPU使用

比如说,程序使用第 2 张显卡(从 0 开始计数)。它的作用是告诉系统和深度学习框架(如 PyTorch 或 TensorFlow)只可见某些 GPU。 export CUDA_VISIBLE_DEVICES1 然后再查看当前使用的显卡: echo $CUDA_VIS…...

【设计模式】享元模式(Flyweight Pattern)

享元模式(Flyweight Pattern)是一种结构型设计模式,它通过共享尽可能多的对象来有效支持大量细粒度的对象。这个模式主要用于减少内存使用和提高性能,特别是在需要创建大量相似对象的场景中。享元模式的核心思想是将对象的状态分为…...

题目 1688: 数据结构-字符串插入

第一种方式字符串 #include<iostream> #include<cstring> #include<algorithm> using namespace std; int main(){string s1,s2;int n;cin>>s1>>s2>>n;s1.insert(n-1,s2);cout<<s1<<endl;return 0; } 第二种方式字符数组 …...

28.攻防世界PHP2

进入场景 扫描目录 [04:12:32] 403 - 303B - /.ht_wsr.txt [04:12:32] 403 - 306B - /.htaccess.bak1 [04:12:32] 403 - 308B - /.htaccess.sample [04:12:…...

QML QT6 WebEngineView 、Echarts使用和数据交互

QML 中的 WebEngineView 是用于显示网页内容的组件,它基于 Qt WebEngine,支持现代网页渲染和与 JavaScript 的交互。它通常用来在 QML 应用中嵌入浏览器或加载在线资源。WebEngineView 可以展示 HTML、CSS、JavaScript 等网页内容,并提供多种属性和方法来控制其行为。 如下…...

SpringBoot 整合 Mail 轻松实现邮件自动推送

简单使用 1、pom 包配置 pom 包里面添加 spring-boot-starter-mail 包引用 <dependencies><dependency> <groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency> </de…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统&#xff0c;可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析&#xff1a;自动解析Markdown文档结构PPT模板分析&#xff1a;分析PPT模板的布局和风格智能布局决策&#xff1a;匹配内容与合适的PPT布局自动…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...