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

漫谈设计模式 [9]:外观模式

引导性开场

菜鸟:老鸟,我最近在做一个项目,感觉代码越来越复杂,我都快看不懂了。尤其是有好几个子系统,它们之间的调用关系让我头疼。

老鸟:复杂的代码确实让人头疼。你有没有考虑过使用设计模式来简化你的代码结构?

菜鸟:设计模式?我听说过一些,但不太了解。你觉得我应该用哪个模式呢?

老鸟:听起来你的问题可能适合用**外观模式(Facade Pattern)**来解决。我们可以一起探讨一下。

渐进式介绍概念

菜鸟:外观模式?能不能解释一下是什么?

老鸟:好,我们先从一个生活中的例子说起。你买了一台新电视,电视上有很多接口,比如HDMI、USB、网线等等。如果每次你都要自己插各种线并调整设置,会很麻烦对吧?

菜鸟:是的,确实很麻烦。

老鸟:于是,你买了一个万能遥控器,这个遥控器可以帮助你一键连接所有设备并调整设置。你只需要按一个按钮,就可以享受电视和其他设备的无缝连接。

菜鸟:听起来不错,这和编程有什么关系呢?

老鸟:在编程中,外观模式就像这个万能遥控器。它提供一个简单的接口,隐藏了复杂的子系统调用。你只需要通过外观接口进行操作,而无需关心内部的复杂逻辑。

Python代码示例,逐步展开

菜鸟:能给我举个例子吗?

老鸟:当然可以。假设你有一个家庭影院系统,包括DVD播放器、投影仪和音响系统。我们先写出这几个子系统的类。

class DVDPlayer:def on(self):print("DVD Player is on")def play(self, movie):print(f"Playing {movie}")class Projector:def on(self):print("Projector is on")def set_input(self, input):print(f"Projector input set to {input}")class SoundSystem:def on(self):print("Sound System is on")def set_volume(self, level):print(f"Volume set to {level}")

菜鸟:每个子系统都有自己的方法,如果我要开电影,需要一个个调用他们的方法对吧?

老鸟:是的,这样会很麻烦。现在我们来创建一个外观类,它提供一个简单的接口来控制整个家庭影院系统。

class HomeTheaterFacade:def __init__(self, dvd_player, projector, sound_system):self.dvd_player = dvd_playerself.projector = projectorself.sound_system = sound_systemdef watch_movie(self, movie):print("Get ready to watch a movie...")self.dvd_player.on()self.dvd_player.play(movie)self.projector.on()self.projector.set_input("DVD")self.sound_system.on()self.sound_system.set_volume(5)print("Movie started!")

菜鸟:哇,这样确实简单多了!我只需要调用watch_movie方法就行了。

老鸟:没错,我们来看看如何使用这个外观类。

dvd_player = DVDPlayer()
projector = Projector()
sound_system = SoundSystem()home_theater = HomeTheaterFacade(dvd_player, projector, sound_system)
home_theater.watch_movie("Inception")

菜鸟:代码变得清晰多了,这样维护也更容易。

问题与反思

菜鸟:如果我不使用外观模式,直接在主代码中调用子系统的方法,会有什么问题吗?

老鸟:最大的麻烦就是代码的复杂性和可维护性。每次你修改子系统的实现,都需要在主代码中找到相关的调用并修改。而使用外观模式,你只需要修改外观类的实现,主代码无需改变。

优势与适用场景

菜鸟:外观模式还有哪些优势呢?

老鸟:外观模式的主要优势包括:

  1. 简化接口:提供一个简单的接口,隐藏底层复杂性。
  2. 松散耦合:减少子系统之间的依赖关系,提高代码的可维护性。
  3. 更好的分层设计:有助于系统分层,使得高层代码更简洁。

适用场景包括:

  • 当你有一个复杂的子系统,需要提供一个简单的接口给客户端。
  • 当你希望对子系统进行解耦,使得子系统的变化不会影响到高层代码。

常见误区与优化建议

菜鸟:听起来外观模式很有用,那有没有什么常见的误区需要注意?

老鸟:有的。一个常见误区是把所有逻辑都放在外观类中,导致外观类变得臃肿。外观类应该只负责协调子系统的调用,而不应该包含太多业务逻辑。

另一个需要注意的是,外观模式并不能完全取代子系统的接口。在某些情况下,客户端可能仍然需要直接调用子系统的方法。

总结与延伸阅读

老鸟:今天我们介绍了外观模式,通过一个家庭影院的例子,你学会了如何使用外观模式来简化代码结构。外观模式的核心思想是提供一个简单的接口,隐藏底层的复杂性。

如果你感兴趣,可以继续学习其他设计模式,比如单例模式、观察者模式等。我推荐《设计模式:可复用面向对象软件的基础》这本书,里面有详细的介绍。

菜鸟:谢谢老鸟,我受益匪浅!我会继续学习其他设计模式的。

老鸟:不客气,编程的道路上我们一起进步!

相关文章:

漫谈设计模式 [9]:外观模式

引导性开场 菜鸟:老鸟,我最近在做一个项目,感觉代码越来越复杂,我都快看不懂了。尤其是有好几个子系统,它们之间的调用关系让我头疼。 老鸟:复杂的代码确实让人头疼。你有没有考虑过使用设计模式来简化你…...

多进程编程

基本概念 进程是一个具有单独功能的程序对某个数据集在处理机上的执行过程,进程也是作为资源分配的一个单位。 进程和程序是相辅相成的,进程是一个动态概念。 进程具有并行性特征。进程具有独立性和异步性。 进程的描述 进程分为三部分:…...

7-Zip压缩包如何添加密码,加密后如何取消

压缩包文件大家经常使用,最熟悉的肯定是RAR、ZIP格式压缩文件,但是7z压缩文件格式也很好用,它是三种压缩文件格式中压缩率最大的。想要将文件压缩到最小,使用7z格式可以达到最大化。那么在使用7z压缩格式的时候,我们可…...

HarmonyOS---应用测试概述

一、应用质量要求 应用质量要求分为应用体验质量建议和应用内容合规要求两大部分。 1、应用体验质量建议 功能数据完备、基础体验要求、HarmonyOS特征增强体验要求。 (1)功能数据完备 (2)基础体验要求 (3)增…...

密码学---真题演练

✨Base加密:题目-base? 靶场网址:https://polarctf.com/ Base100加密!!! 得到的新的一串密码是 rot47 密码,属于凯撒密码的一种变体. ✨斐波那契:题目-FB 从第三项开始,每一项都等…...

时间日期工具类

时间日期工具类 import java.time.*; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit;public class DateTimeUtils {private static final String DEFAULT_DATE_FORMAT "yyyy-MM-dd";private static final String DEFAULT_TIME_…...

linux中vim常用命令大全

前言 Linux有大量的配置文件,所以 Linux的文本处理工具也是比较多的,其中编辑一些配置文件时,常用的工具就是 vim。在Linux中,Vim编辑器是一个非常强大的文本编辑工具,它提供了多种模式和命令来满足不同的编辑需求。以…...

计算机的错误计算(八十九)

摘要 探讨反双曲余切函数 acoth(x) 在 附近的计算精度问题。 Acoth(x) 函数的定义为: 其中 x 的绝对值大于 1 . 例1. 计算 acoth(1.000000000002) . 不妨在 Excel 的单元格中计算,则有: 若在Python中用定义直接计算,则有几乎…...

深入理解java并发编程之aqs框架

跟synchronized 相比较,可重入锁ReentrankLock其实原理有什么不同? 所得基本原理是为了达到一个目的;就是让所有线程都能看到某种标记。synchronized通过在对象头中设置标记实现了这一目的,是一种JVM原生的锁实现方式。而Reentran…...

ubuntu配置tftp、nfs

tftp配置 tftp是简单文件传输协议,基于udp实现传输。这里的简单文件,指的是不复杂、开销不大的文件。 先在ubuntu中安装tftp,输入命令:sudo apt-get install tftp-hpa tftpd-hpa。 接着配置tftp。 输入命令:sudo v…...

Sklearn的datasets模块与自带数据集介绍

datasets 模块 用 dir() 函数查看 datasets 模块的所有属性和函数 import sklearn.datasets as datasets# 列出 sklearn.datasets 模块中的所有属性和函数 print(dir(datasets)) datasets 模块下的数据集有三种类型: (1)load系列的经典数…...

css 个人喜欢的样式 速查笔记

起因&#xff0c; 目的: 记录自己喜欢的&#xff0c; 觉得比较好看的 css. 下次用的时候&#xff0c;直接复制&#xff0c;很方便。 1. 个人 html 模板&#xff0c; 导入常用的 link 设置英语字体: Noto导入默认的 css使用网络 icon 图标导入 Bootstrap css 框架 html <…...

C/C++ let __DATE__ format to “YYYY-MM-DD“

C/C let DATE format to “YYYY-MM-DD” code&#xff1a; #include <iostream> #include <string>class compileDate {// 静态函数&#xff0c;用来格式化并返回编译日期 static std::string formatCompileDate() {// 编译时的日期&#xff0c;格式为 "MMM…...

git如何灵活切换本地账号对应远程github的两个账号

git如何灵活切换本地账号对应远程github的两个账号 问题&#xff1a; 有时候我们会同时维护两个github的账号里面的仓库内容&#xff0c;这时候本地git需要频繁的切换ssh&#xff0c;以方便灵活的与两个账号的仓库可以通信。这篇日记将阐述我是怎么解决这个问题的。1. 第一个账…...

Python中实现函数的递归调用

在Python中&#xff0c;函数的递归调用是一种非常强大且常用的编程技巧&#xff0c;它允许函数在其执行过程中调用自身。递归调用在解决许多问题时都显得尤为方便&#xff0c;比如遍历树形结构、计算阶乘、实现快速排序等。然而&#xff0c;递归也需要谨慎使用&#xff0c;因为…...

Multisim使用手册

目录 原件库&#xff1a; 基础元件库&#xff1a; 最右侧的分析仪们&#xff1a; 示波器&#xff1a; 交流分析&#xff1a; 操作&#xff1a; dB 一、幅频特性曲线 二、相频特性曲线 下载资源&#xff08;有汉化&#xff09;&#xff1a;Multisim 14.0电路设计与仿真…...

线程的六种状态

优质博文&#xff1a;IT-BLOG-CN 线程的状态在Thread.State这个枚举类型中定义&#xff1a;共有6种状态&#xff0c;可以调用线程Thread种的getState()方法获取当前线程状态。 public enum State { /** * 新建状态(New)&#xff1a; * 当用new操作符创建一个线程时&#…...

全球热门剪辑软件大搜罗

如果你要为你的视频进行配音那肯定离不开音频剪辑软件&#xff0c;现在有不少音频剪辑软件免费版本就可以实现我们并不复杂的音频剪辑操作。这次我就给你分享几款能提高剪辑效率的音频剪辑工具。 1.福晰音频剪辑 链接直达>>https://www.foxitsoftware.cn/audio-clip/ …...

swagger-bootstrap-ui页面空白,也没报错

回想起来&#xff0c;代码层面没有进行什么大的调整&#xff0c;增加了配置文件&#xff0c;application.yml中的 spring:profiles:active: sms # dev --> smsname: sms-server swagger配置未调整导致空白 修改profile 问题解决...

15.2 JDBC数据库编程2

15.2.1 数据库访问步骤 使用JDBC API连接和访问数据库&#xff0c;一般分为以下5个步骤: (1) 加载驱动程序 (2) 建立连接对象 (3) 创建语句对象 (4) 获得SQL语句的执行结果 (5) 关闭建立的对象&#xff0c;释放资源 下面将详细描述这些步骤 15.2.2 加载驱动程序 要使…...

后进先出(LIFO)详解

LIFO 是 Last In, First Out 的缩写&#xff0c;中文译为后进先出。这是一种数据结构的工作原则&#xff0c;类似于一摞盘子或一叠书本&#xff1a; 最后放进去的元素最先出来 -想象往筒状容器里放盘子&#xff1a; &#xff08;1&#xff09;你放进的最后一个盘子&#xff08…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库&#xff0c;用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

边缘计算医疗风险自查APP开发方案

核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh&#xff1f; debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用

一、方案背景​ 在现代生产与生活场景中&#xff0c;如工厂高危作业区、医院手术室、公共场景等&#xff0c;人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式&#xff0c;存在效率低、覆盖面不足、判断主观性强等问题&#xff0c;难以满足对人员打手机行为精…...

数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !

我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...

React从基础入门到高级实战:React 实战项目 - 项目五:微前端与模块化架构

React 实战项目&#xff1a;微前端与模块化架构 欢迎来到 React 开发教程专栏 的第 30 篇&#xff01;在前 29 篇文章中&#xff0c;我们从 React 的基础概念逐步深入到高级技巧&#xff0c;涵盖了组件设计、状态管理、路由配置、性能优化和企业级应用等核心内容。这一次&…...