【设计模式】深入浅出--外观模式

文章目录

  • 前言
  • 一、外观模式介绍
  • 二、案例场景
  • 三、外观模式优缺点
  • 四、外观模式应用场景
  • 总结

前言

不知道大家有没有比较过自己泡茶和去茶馆喝茶的区别,如果是自己泡茶需要自行准备茶叶、茶具和开水,而去茶馆喝茶,最简单的方式就是跟茶馆服务员说想要一杯什么样的茶,是铁观音、碧螺春还是西湖龙井?正因为茶馆有服务员,顾客无须直接和茶叶、茶具、开水等交互,整个泡茶过程由服务员来完成,顾客只需与服务员交互即可,整个过程非常简单省事。

以上这种场景类似设计模式中的外观模式,也叫做门面模式

外观模式通过引入一个新的外观类来实现该功能,外观类充当了“服务员”的角色,它为多个业务类的调用提供了一个统一的入口,简化了类与类之间的交互。

本文我们一起来聊聊外观模式。

一、外观模式介绍

外观模式是一种使用频率非常高的结构型设计模式,它通过引入一个外观角色来简化客户端与子系统之间的交互为复杂的子系统调用提供一个统一的入口降低子系统与客户端的耦合度,且客户端调用非常方便

外观模式结构图:
在这里插入图片描述

  • Facade(外观角色):在客户端可以调用它的方法,在外观角色中可以知道相关的(一个或者多个)子系统的功能和责任;在正常情况下,它将所有从客户端发来的请求委派到相应的子系统去,传递给相应的子系统对象处理。
  • SubSystem(子系统角色):在软件系统中可以有一个或者多个子系统角色,每一个子系统可以不是一个单独的类,而是一个类的集合,它实现子系统的功能;每一个子系统都可以被客户端直接调用,或者被外观角色调用,它处理由外观类传过来的请求;子系统并不知道外观的存在,对于子系统而言,外观角色仅仅是另外一个客户端而已。

二、案例场景

  • 场景一:自己泡茶,整个过程应该是“烧开水->拿茶具->泡茶叶”然后喝茶。

    定义一个饮用水类:DrinkableWater

    /**
     * 烧水
     */
    public class DrinkableWater {
    
        public DrinkableWater(){
            System.out.println("水准备好了");
        }
    
        //烧水
        public void facadeWater(){
            System.out.println("水烧开了");
        }
    }
    

    定义一个茶叶类:Tea

    /**
     * 茶叶
     */
    public class Tea {
    
        public Tea(){
            System.out.println("茶叶准备好了");
        }
    
        //取茶
        public void facadeTea(){
            System.out.println("可以泡茶了");
        }
    }
    

    定义一个茶杯类:TeaCup

    /**
     * 茶杯
     */
    public class TeaCup {
    
        public TeaCup(){
            System.out.println("茶杯准备好了");
        }
    
        //泡茶
        public void facadeTeaCup(Tea tea){
            tea.facadeTea();
            System.out.println("茶叶泡进茶杯了");
            System.out.println("茶冲好了");
        }
    }
    

    准备就绪,开始泡茶

    public static void main(String[] args) {
        System.out.println("准备泡茶...");
        DrinkableWater drinkableWater = new DrinkableWater();
        TeaCup teaCup = new TeaCup();
        Tea tea = new Tea();
    
        drinkableWater.facadeWater();
        teaCup.facadeTeaCup(tea);
        System.out.println("喝茶...");
    }
    

    运行结果

    准备泡茶...
    水准备好了
    茶杯准备好了
    茶叶准备好了
    水烧开了
    可以泡茶了
    茶叶泡进茶杯了
    茶冲好了
    喝茶...
    
  • 场景二:去茶馆喝茶,不用自己动手泡茶了,直接告诉茶馆的服务员就行了。

    定义一个服务员类:

    /**
     * 服务员
     */
    public class Waiter {
    
        private DrinkableWater drinkableWater = new DrinkableWater();
        private TeaCup teaCup = new TeaCup();
        private Tea tea = new Tea();
    
        //获得一杯茶
        public void getTea(){
            drinkableWater.facadeWater();
            teaCup.facadeTeaCup(tea);
        }
    }
    

    客户类:Customer

    public class Customer {
    
        public static void main(String[] args) {
            //叫店小二
            Waiter waiter = new Waiter();
            //从店小二那获得一杯茶
            waiter.getTea();
        }
    }
    

    运行结果

    水准备好了
    茶杯准备好了
    茶叶准备好了
    水烧开了
    可以泡茶了
    茶叶泡进茶杯了
    茶冲好了
    

在上面的泡茶的例子中,客人就是客户角色,茶馆服务员就是门面角色,茶具、饮用水、茶叶就是子系统角色。

代码看上去都很简单,也许你感觉二者区别不是很大,假如在软件开发中三个子系统之间有先后顺序,还有来自不同网络开销,我们通过门面模式提供的方法,就屏蔽了这些差异,让我们只需要调用门面角色提供给我们的方法即可

三、外观模式优缺点

  • 优点
    • 减少系统的相互依赖
      如果我们不使用门面模式, 外界访问直接深入到子系统内部, 相互之间是一种强耦合关系, 你死我就死, 你活我才能活, 这样的强依赖是系统设计所不能接受的, 门面模式的出现就很好地解决了该问题, 所有的依赖都是对门面对象的依赖, 与子系统无关。
    • 提高安全性
      想让你访问子系统的哪些业务就开通哪些逻辑, 不在门面上开通的方法, 你休想访问到。
  • 缺点
    • 不能很好地限制客户端直接使用子系统类,如果对客户端访问子系统类做太多的限制则减少了可变性和灵活性。
    • 如果设计不当,增加新的子系统可能需要修改外观类的源代码,违背了开闭原则。

四、外观模式应用场景

  1. 解决易用性问题
    门面模式可以用来封装系统的底层实现,隐藏系统的复杂性,提供一组更加简单易用、更高层的接口。
  2. 解决性能问题
    通过将多个接口调用替换为一个门面接口调用,减少网络通信成本,提高客户端的响应速度。
  3. 解决分布式事务问题
    需要调用多个子系统的接口方法,而这些接口要么都成功,要么都失败,我们就可以利用门面模式包裹这些子系统接口,然后通过某种方法保证这些接口在一个事务中完成。

总结

  • 在几乎所有的软件中都能够找到外观模式的应用,如绝大多数B/S系统都有一个首页或者导航页面,大部分C/S系统都提供了菜单或者工具栏,在这里,首页和导航页面就是B/S系统的外观角色,而菜单和工具栏就是C/S系统的外观角色,通过它们用户可以快速访问子系统,降低了系统的复杂程度。所有涉及到与多个业务对象交互的场景都可以考虑使用外观模式进行重构。

  • 很多时候不是设计模式没有用,而是自己编程开发经验不足导致即使学了设计模式也很难驾驭。

  • 毕竟这些知识都是经过一些实际操作提炼出来的精华。

希望对你有帮助,如有问题欢迎评论区讨论!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【UE】暂停游戏界面及功能实现

效果 步骤 1. 首先在项目设置中添加一个暂停的操作映射 2. 新建一个控件蓝图,命名为“PauseMenuWidget” 3. 打开“ThirdPersonCharacter”,添加一个布尔类型变量,命名为“isScreenShow”,用于判断当前玩家是否打开了暂停界面 在…

S7-200 SMART 和 S7-1200PLC进行PROFINET IO通信

从 S7-200 SMART V2.5 版本开始,S7-200 SMART 开始支持做 PROFINET IO 通信的智能设备。因此,两个 S7-200 SMART 之间可以进行 PROFINET IO 通信,一个CPU 作PROFINET IO 控制器,一个 CPU 作 PROFINET 通信的设备。组态的时候有两种方法,一种是通过硬件目录组态另外一种是通…

原理+配置+实战,Canal一套带走

前几天在网上冲浪的时候发现了一个比较成熟的开源中间件——Canal。在了解了它的工作原理和使用场景后,顿时产生了浓厚的兴趣。今天,就让我们跟随阿Q的脚步,一起来揭开它神秘的面纱吧。 简介 canal 翻译为管道,主要用途是基于 M…

EEG源定位

导读 自从脑电图(EEG)被发现以来,人们希望EEG能提供一个了解大脑的窗口,研究人员一直试图用EEG无创定位大脑中产生头皮电位的神经元活动。20世纪50年代的早期探索使用电场理论从头皮电位分布推断大脑中电流偶极子的位置和方向,引发了大量定量…

2023美赛春季赛Z题模型代码

已经完成模型代码,仅供大家参考,需要更多请看文末 一、问题分析 首先需要收集与奥运会举办城市/国家相关的历史数据。这需要涉及诸如经济、土地利用、人类满意度(包括运动员和观众)、旅行、基础设施建设、环境影响等多个方面。数…

日常项目技术方案脉络

开篇引砖 软件在其生命周期中,当其进入稳定期后,大部分时间都处于迭代更新维护阶段。在这漫长的三年甚至五年的存活期内,我们需要面对林林种种大大小小的需求。今天我们就聊聊在这段期间,如何快速产出一份合格的技术方案。 方案给…

Banana Pi BPI-Centi-S3 使用MicroPython编程显示JPG图片

BPI-Centi-S3是我们新推出的一款板载1.9英寸彩屏的小尺寸ESP32-S3开发板! BPI-Centi-S3 banana-pi wiki BPI-Centi-S3 bpi-steam wiki 1 关键特性 ESP32-S3,Xtensa 32 bit LX72M PSRAM , 8M FLASH2.4G WIFI ,Bluetooth 5 ,Blue…

基于鲸鱼算法的极限学习机(ELM)回归预测-附代码

基于鲸鱼算法的极限学习机(ELM)回归预测 文章目录 基于鲸鱼算法的极限学习机(ELM)回归预测1.极限学习机原理概述2.ELM学习算法3.回归问题数据处理4.基于鲸鱼算法优化的ELM5.测试结果6.参考文献7.Matlab代码 摘要:本文利用鲸鱼算法对极限学习机进行优化,并…

微服务学习之面试知识相关总结(Nacos、MQ)

文章目录 壹 微服务Nacos1.1 SpringCloud常见组件1.2 Nacos的服务注册表结构1.3 Nacos如何支撑内部数十万服务注册压力1.4 Nacos避免并发读写冲突问1.5 Nacos与Eureka的区别1.6 Sentinel的限流与Gateway的限流的差别1.7 Sentinel的线程隔离与Hystix的线程隔离的差别 贰 MQ知识2…

7款神仙级非常漂亮的 Linux 操作系统UI,你都用过吗

Linux 的发行版有很多,这里罗列7个漂亮的 Linux 发行版,可以说是Linux操作系统界的颜值担当了。 1、elementary OS 网站:https://elementaryos.cn elementary OS操作系统是最漂亮的Linux发行版之一。它基于macOS外观,同时为Linu…

C# 特性(Attribute)

一、特性(Attribute)定义 特性(Attribute)是用于在运行时传递程序中各种元素(比如类、方法、结构、枚举、组件等)的行为信息的声明性标签。您可以通过使用特性向程序添加声明性信息。 特性使用中括号…

AI智能课程第一讲:chatgpt介绍

AI应用现状 用AI艺术创作 一个小女孩打折手电筒在侏罗世纪公园找恐龙。 AI用于医疗行业 AI辅助驾驶 AI广告投放上的应用 什么是chatgpt? chatgpt相关技术的发展 为什么用chatgpt写代码会特别的快呢? 因为它集成了GitHub上所有开发者的库公用资源&…

供需两端催化口腔医疗服务市场增长 未来将呈现线上化、智能化、品质化三大趋势

一、口腔医疗服务行业概述 口腔由唇、颊、舌、腭、涎腺、牙和颌骨等部分组成。口腔疾病种类繁多,伴随人全生命周期,常见疾病有龋病、牙周疾病、牙髓病、根尖周病、牙齿缺损、错颌畸形等,多数口腔疾病的发病率高,诊疗需求大。除此…

原型设计工具即时设计、Axure、Figma、Sketch,哪个更好用?

在线网页原型图设计软件的使用与桌面端相比具备优势,因为在线网页原型图设计软件的使用全程不需要安装,而且在线网页原型图设计软件也没有任何地点上的限制,更主要的是在线网页原型图设计软件在操作系统上也没有限制,不论是现在使…

GPT模型支持下的Python-GEE遥感云大数据分析、管理与可视化技术应用

随着航空、航天、近地空间等多个遥感平台的不断发展,近年来遥感技术突飞猛进。由此,遥感数据的空间、时间、光谱分辨率不断提高,数据量也大幅增长,使其越来越具有大数据特征。对于相关研究而言,遥感大数据的出现为其提…

服务型企业如何使用飞项实现项目化管理?

服务型企业的业务模式一般都是按项目来运作的,其业务分为售前,售中和售后三个阶段,分别由不同部门和人员对客户进行个性化服务。在这个过程中需要对人、流程和知识的高效统筹管理,即项目的整体管理,因此存在着不小的挑…

git lfs简易使用教程

参考资料: https://zzz.buzz/zh/2016/04/19/the-guide-to-git-lfs/ 这篇随笔简单记录一下git lfs的使用教程,只记录最为常用的部分,并阐述原理,方便后面查阅。 首先说明一下git lfs的原理,看名称:git lfs。…

算法:(力扣)(牛客)打印螺旋矩阵题

手撕螺旋矩阵 题目思路解题 题目 描述:给定一个m x n大小的矩阵(m行,n列),按螺旋的顺序返回矩阵中的所有元素。数据范围:0 \le n,m \le 100≤n,m≤10,矩阵中任意元素都满足 |val| \le 100∣val…

如何优化语音交友app开发的搜索和匹配算法

语音交友app开发的挑战 在当今社交媒体行业中,语音交友app开发已经成为一个热门的领域。越来越多的人开始使用语音交友app来寻找新的朋友,这也为开发者们带来了许多机会。然而,这个领域也面临着一些挑战。其中一个最大的挑战是如何优化搜索和…

全志v851s uart3 设置成普通串口收发

本文转载自:https://bbs.aw-ol.com/topic/3281/ 由于UART0 被设定为系统dubug 输出(简单来说就是将ttyS0 设定为console),所以使用UART3 作为普通的串口,进行与别的设备通信。 1. 查看硬件电路图SCH_Schematic1_2022…