外观模式的理解和实践

        外观模式(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. 不易扩展:当需要增加新的子系统组件时,可能需要修改外观类,违反了开闭原则(对扩展开放,对修改关闭)。

总结

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/64482.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《应用导航设计:裂变式路由风暴来袭》——HarmonyOS开发项目时的Navigation路由奇妙使用

文章目录 应用导航设计引言概述场景示例基本实现推荐方案路由管理模块的实现页面跳转实现 业务实现中的关键点动态加载路由栈管理 应用导航设计 引言 在大型应用开发中,如何高效地设计应用导航,处理多模块间的路由跳转与解耦,始终是一个关键…

【腾讯云】AI驱动TDSQL-C Serveress 数据库技术实战营-如何是从0到1体验电商可视化分析小助手得统计功能,一句话就能输出目标统计图

欢迎来到《小5讲堂》 这是《腾讯云》系列文章,每篇文章将以博主理解的角度展开讲解。 温馨提示:博主能力有限,理解水平有限,若有不对之处望指正! 目录 背景效果图流程图创建数据库基本信息数据库配置设置密码控制台开启…

win服务器的架设、windows server 2012 R2 系统的下载与安装使用

文章目录 windows server 2012 R2 系统的下载与安装使用1 windows server 2012 的下载2 打开 VMware 虚拟机软件(1)新建虚拟机(2)设置虚拟机(3)打开虚拟机 windows server 2012(4)进…

如何在谷歌浏览器中开启安全浏览

在数字化时代,网络安全变得愈发重要。作为全球最受欢迎的网络浏览器之一,谷歌浏览器提供了多种功能来保护用户的在线安全。本文将详细介绍如何在谷歌浏览器中开启安全浏览,并额外提供一些有用的页面滚动设置、地址栏快捷搜索和跟踪防护的相关…

djiango DRF的使用

djiango DRF的使用 一 、初始 DRF序列化环境安装环境配置数据模型定义定义DRF序列化模型对象 二 、DRF请求和响应请求对象(Request objects)响应对象(Response objects)状态码(Status codes)包装&#xff0…

计算机网络-HTTP协议

HTTP HTTP是一种不保存状态,即无状态的协议。HTTP协议自身不对请求和响应之间的通信进行保存。为了保存状态因此后面也有一些技术产生比如Cookies技术。 HTTP是通过URI定位网上的资源,理论上将URI可以访问互联网上的任意资源。 如果不是访问特定的资源…

CTFHub 命令注入-综合练习(学习记录)

综合过滤练习 命令分隔符的绕过姿势 ; %0a %0d & 那我们使用%0a试试,发现ls命令被成功执行 /?ip127.0.0.1%0als 发现一个名为flag_is_here的文件夹和index.php的文件,那么我们还是使用cd命令进入到文件夹下 http://challenge-438c1c1fb670566b.sa…

【AI知识】逻辑回归介绍+ 做二分类任务的实例(代码可视化)

1. 分类的基本概念 在机器学习的有监督学习中,分类一种常见任务,它的目标是将输入数据分类到预定的类别中。具体来说: 分类任务的常见应用: 垃圾邮件分类:判断一封电子邮件是否是垃圾邮件 。 医学诊断:…

为SSH2协议服务器的用户设置密钥

目录 私钥的创建1. 在服务器上直接生成2. 如果需要配置免密登录3. 查看生成的密钥 导出私钥至SSH用户获取sudo权限 新的一台服务器类型是SSH2:这表示服务器支持SSH(Secure Shell)协议的第二个版本。SSH是一个网络协议,用于加密方式…

level2逐笔委托查询接口

沪深逐笔委托队列查询 前置步骤 分配数据库服务器 查询模板 以下是沪深委托队列查询的请求模板&#xff1a; http://<数据库服务器>/sql?modeorder_book&code<股票代码>&offset<offset>&token<token>查询参数说明 参数名类型说明mo…

文献研读|基于像素语义层面图像重建的AI生成图像检测

前言&#xff1a;本篇文章主要对基于重建的AI生成图像检测的四篇相关工作进行介绍&#xff0c;分别为基于像素层面重建的检测方法 DIRE 和 Aeroblade&#xff0c;以及基于语义层面重建的检测方法 SimGIR 和 Zerofake&#xff1b;并对相应方法进行比较。 相关文章&#xff1a;论…

VScode MAC按任意键关闭终端 想要访问桌面文件

说明 最近配置MAC上CPP的运行环境&#xff0c;在安装必要的CPP插件后&#xff0c;配置launch和task等json文件后&#xff0c;点击运行三角形&#xff0c;每次都会跳出main想要访问桌面上的文件。并且输出也是在调试控制台&#xff0c;非常逆天。 尝试 尝试1:尽管我尝试将ta…

Linux Shell 脚本编程基础知识篇

ℹ️大家好&#xff0c;我是练小杰&#xff0c;从本文是Linux shell脚本编程的基础知识内容&#xff0c;后续我会不断补充~~ 更多Linux 相关内容请点击&#x1f449;“Linux专栏”~ 假面驾驭&#xff0c;时王&#xff0c;假面骑士时王~~ 文章目录 什么是 Linux Shell主要功能…

QT绘制同心扇形

void ChartForm::paintEvent(QPaintEvent *) {QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing);// 设置抗锯齿painter.save();// 设置无边框&#xff08;不需要设置QPen&#xff0c;因为默认是不绘制边框的&#xff09;QPen pen(Qt::NoPen);// QPen pen…

TL3568/TL3562更改主机名,在Kernel用menuconfig失效

前言 最近在玩RK3562开发板&#xff0c;想改串口调试时看到的主机名&#xff0c;开发板的主机名默认是RK3562-Tronlong&#xff0c;如图&#xff1a; 按照之前玩T113开发版&#xff0c;在Kernel通过make menuconfig&#xff0c;可以改。但是在这个RK3562&#xff0c;改了后&…

【PLL】ISSCC 2024 Tutorial: Calibration Techniques in PLLs

1. 数字辅助模拟电路 为什么要辅助&#xff0c;或替换模拟电路&#xff1f; 利用CMOS管子尺寸缩小&#xff0c;降低功耗 和 减小面积校正模拟电路的 非线性行为 和 失配 数字辅助的好处&#xff1a; 简化模拟电路设计提高能源效率&#xff0c;提高准确度 2. 锁相环基础 2.1 概…

STM32-笔记5-按键点灯(中断方法)

1、复制03-流水灯项目&#xff0c;重命名06-按键点灯&#xff08;中断法&#xff09; 在\Drivers\BSP目录下创建一个文件夹exti&#xff0c;在该文件夹下&#xff0c;创建两个文件exti.c和exti.h文件&#xff0c;并且把这两个文件加载到项目中&#xff0c;打开项目工程文件 加载…

Mvc、Springmvc框架

一.Mvc&#xff1a; 1.概念&#xff1a; MVC它是一种设计理念。把程序按照指定的结构来划分: Model模型 、View视图 、Controller控制层&#xff1b; 结构图&#xff1a; 二.Springmvc: 1.概念&#xff1a; springmvc框架它是spring框架的一个分支。它是按照mvc架构思想设计…

spring使用rabbitmq当rabbitmq集群节点挂掉 spring rabbitmq怎么保证高可用,rabbitmq网络怎么重新连接

##spring rabbitmq代码示例 Controller代码 import com.alibaba.fastjson.JSONObject; import com.newland.mi.config.RabbitDMMQConfig; import org.springframework.amqp.core.Message; import org.springframework.amqp.core.MessageProperties; import org.springframewo…

前端面试问题集合

0 HTML5相关 websocket WebSocket 使用ws或wss协议&#xff0c;Websocket是一个持久化的协议&#xff0c;相对于HTTP这种非持久的协议来说。WebSocket API最伟大之处在于服务器和客户端可以在给定的时间范围内的任意时刻&#xff0c;相互推送信息。WebSocket并不限于以Ajax(或X…