当前位置: 首页 > 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…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架&#xff0c;专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用&#xff0c;其中包含三个使用通用基本模板的页面。在此…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

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

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

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

Go语言多线程问题

打印零与奇偶数&#xff08;leetcode 1116&#xff09; 方法1&#xff1a;使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...

tomcat入门

1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效&#xff0c;稳定&#xff0c;易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...

毫米波雷达基础理论(3D+4D)

3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文&#xff1a; 一文入门汽车毫米波雷达基本原理 &#xff1a;https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...

在 Spring Boot 项目里,MYSQL中json类型字段使用

前言&#xff1a; 因为程序特殊需求导致&#xff0c;需要mysql数据库存储json类型数据&#xff0c;因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...