设计模式——外观模式(结构型)

引言

外观模式是一种结构型设计模式, 能为程序库、 框架或其他复杂类提供一个简单的接口。

问题

假设你必须在代码中使用某个复杂的库或框架中的众多对象。 正常情况下, 你需要负责所有对象的初始化工作、 管理其依赖关系并按正确的顺序执行方法等。

最终, 程序中类的业务逻辑将与第三方类的实现细节紧密耦合, 使得理解和维护代码的工作很难进行。

解决方案

外观类为包含许多活动部件的复杂子系统提供一个简单的接口。 与直接调用子系统相比, 外观提供的功能可能比较有限, 但它却包含了客户端真正关心的功能。

如果你的程序需要与包含几十种功能的复杂库整合, 但只需使用其中非常少的功能, 那么使用外观模式会非常方便,

例如, 上传猫咪搞笑短视频到社交媒体网站的应用可能会用到专业的视频转换库, 但它只需使用一个包含 encode­(filename, format)方法 (以文件名与文件格式为参数进行编码的方法) 的类即可。 在创建这个类并将其连接到视频转换库后, 你就拥有了自己的第一个外观。

真实世界类比

当你通过电话给商店下达订单时, 接线员就是该商店的所有服务和部门的外观。 接线员为你提供了一个同购物系统、 支付网关和各种送货服务进行互动的简单语音接口。

外观模式结构 

伪代码

在本例中, 外观模式简化了客户端与复杂视频转换框架之间的交互。

你可以创建一个封装所需功能并隐藏其他代码的外观类, 从而无需使全部代码直接与数十个框架类进行交互。 该结构还能将未来框架升级或更换所造成的影响最小化, 因为你只需修改程序中外观方法的实现即可。

// 这里有复杂第三方视频转换框架中的一些类。我们不知晓其中的代码,因此无法
// 对其进行简化。

class VideoFile
// ……

class OggCompressionCodec
// ……

class MPEG4CompressionCodec
// ……

class CodecFactory
// ……

class BitrateReader
// ……

class AudioMixer
// ……


// 为了将框架的复杂性隐藏在一个简单接口背后,我们创建了一个外观类。它是在
// 功能性和简洁性之间做出的权衡。
class VideoConverter is
    method convert(filename, format):File is
        file = new VideoFile(filename)
        sourceCodec = (new CodecFactory).extract(file)
        if (format == "mp4")
            destinationCodec = new MPEG4CompressionCodec()
        else
            destinationCodec = new OggCompressionCodec()
        buffer = BitrateReader.read(filename, sourceCodec)
        result = BitrateReader.convert(buffer, destinationCodec)
        result = (new AudioMixer()).fix(result)
        return new File(result)

// 应用程序的类并不依赖于复杂框架中成千上万的类。同样,如果你决定更换框架,
// 那只需重写外观类即可。
class Application is
    method main() is
        convertor = new VideoConverter()
        mp4 = convertor.convert("funny-cats-video.ogg", "mp4")
        mp4.save()

外观模式适合应用场景

 如果你需要一个指向复杂子系统的直接接口, 且该接口的功能有限, 则可以使用外观模式。

子系统通常会随着时间的推进变得越来越复杂。 即便是应用了设计模式, 通常你也会创建更多的类。 尽管在多种情形中子系统可能是更灵活或易于复用的, 但其所需的配置和样板代码数量将会增长得更快。 为了解决这个问题, 外观将会提供指向子系统中最常用功能的快捷方式, 能够满足客户端的大部分需求。

 如果需要将子系统组织为多层结构, 可以使用外观。

创建外观来定义子系统中各层次的入口。 你可以要求子系统仅使用外观来进行交互, 以减少子系统之间的耦合。

让我们回到视频转换框架的例子。 该框架可以拆分为两个层次: 音频相关和视频相关。 你可以为每个层次创建一个外观, 然后要求各层的类必须通过这些外观进行交互。 这种方式看上去与中介者模式非常相似。

实现方式

  1. 考虑能否在现有子系统的基础上提供一个更简单的接口。 如果该接口能让客户端代码独立于众多子系统类, 那么你的方向就是正确的。

  2. 在一个新的外观类中声明并实现该接口。 外观应将客户端代码的调用重定向到子系统中的相应对象处。 如果客户端代码没有对子系统进行初始化, 也没有对其后续生命周期进行管理, 那么外观必须完成此类工作。

  3. 如果要充分发挥这一模式的优势, 你必须确保所有客户端代码仅通过外观来与子系统进行交互。 此后客户端代码将不会受到任何由子系统代码修改而造成的影响, 比如子系统升级后, 你只需修改外观中的代码即可。

  4. 如果外观变得过于臃肿, 你可以考虑将其部分行为抽取为一个新的专用外观类。

外观模式优缺点

  •  你可以让自己的代码独立于复杂子系统。
  •  外观可能成为与程序中所有类都耦合的上帝对象。

与其他模式的关系

  • 外观模式为现有对象定义了一个新接口, 适配器则会试图运用已有的接口。 适配器通常只封装一个对象, 外观通常会作用于整个对象子系统上。

  • 当只需对客户端代码隐藏子系统创建对象的方式时, 你可以使用抽象工厂模式来代替外观。

  • 享元模式展示了如何生成大量的小型对象, 外观则展示了如何用一个对象来代表整个子系统。

  • 外观和中介者模式的职责类似: 它们都尝试在大量紧密耦合的类中组织起合作。

    • 外观为子系统中的所有对象定义了一个简单接口, 但是它不提供任何新功能。 子系统本身不会意识到外观的存在。 子系统中的对象可以直接进行交流。
    • 中介者将系统中组件的沟通行为中心化。 各组件只知道中介者对象, 无法直接相互交流。
  • 外观类通常可以转换为单例模式类, 因为在大部分情况下一个外观对象就足够了。

  • 外观与代理模式的相似之处在于它们都缓存了一个复杂实体并自行对其进行初始化。 代理与其服务对象遵循同一接口, 使得自己和服务对象可以互换, 在这一点上它与外观不同。

 

 

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

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

相关文章

第1章:企业级研发测试流程

通过实际(自研互联网)企业的研发流程一览图。 我们发现分为9个阶段,当然每个公司细节并不一样。 所以我希望你能理解这句话: 一切的流程、行为、结果都是围绕“产品质量”这4个字开展活动。而作为测试,你该考虑的是如何…

26.Java安卓程序设计-基于SSM框架Android的网店系统设计与实现

1. 引言 1.1 背景 介绍网店系统的背景,说明为什么设计这个系统以及系统的重要性。 1.2 研究目的 阐述设计基于SSM框架的Android网店系统的目标和意义。 2. 需求分析 2.1 行业背景 分析网店行业的特点和需求,以及目前市场上同类系统的不足之处。 …

2012-12-12 下载ndk编译出so和可执行文件,放到android 真机运行,包含源码。

一、下载ndk链接NDK 下载 | Android NDK | Android Developers 二、解压ndk后得到下面的文件,里面包含ndk-build.cmd,这个是用来编译的。 三、Android.mk和C源码。完整源码下载路径https://download.csdn.net/download/qq_37858386/88622702 3.1 A…

SpringIOC之LoadTimeWeavingConfigurer

博主介绍:✌全网粉丝5W,全栈开发工程师,从事多年软件开发,在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战,博主也曾写过优秀论文,查重率极低,在这方面有丰富的经验…

spring 笔记七 Spring JdbcTemplate

文章目录 Spring JdbcTemplateJdbcTemplate概述JdbcTemplate开发步骤Spring产生JdbcTemplate对象 Spring JdbcTemplate JdbcTemplate概述 它是spring框架中提供的一个对象,是对原始繁琐的JdbcAPI对象的简单封装。spring框架为我们提供了很多的操作模板类。例如&am…

Python基础教程——制作一个宿舍管理系统(完整版,附源码)

今天我们一起学习一个新的小案例——宿舍管理系统。主要涉及列表、字典的初始化、增加、删除、修改和查询操作,以及函数的定义和调用。 一、需求: 有操作指引界面,显示操作号 能添加一个新的入住学生信息,包括学生姓名、宿舍号床…

vue3引入Echarts图表

说明:echarts是父组件,stack是子组件,将stack引入到echarts文件中 查看echarts.vue时可看到stack.vue中的图表 # # # 引入方式 第一步 Echarts官网:快速上手 - 使用手册 - Apache ECharts 第二步 在控制台安装Echarts模块…

25.Java程序设计-基于SSM框架的微信小程序校园求职系统的设计与实现

1. 引言 1.1 背景 介绍校园求职系统的背景,说明为什么设计这个系统以及系统的重要性。 1.2 研究目的 阐述设计基于SSM框架的微信小程序校园求职系统的目标和意义。 2. 需求分析 2.1 行业背景 分析校园求职行业的特点和需求,以及目前市场上同类系统…

基于Java的教学信息反馈系统设计与实现(源码+调试)

项目描述 临近学期结束,还是毕业设计,你还在做java程序网络编程,期末作业,老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。今天给大家介绍一篇基于Java的教学信息反馈…

高频Postman接口测试面试题

一、Postman在工作中使用流程是什么样的? 新建集合管理根据接口所属的模块,在集合中不同模块下编写接口测试用例处理接口之间的数据关联操作添加环境变量在tests tab下中增加断言调试接口,确保接口能被正常调用批量运行用例或者导出通过Newm…

Dubbo 快速入门使用教程

文章目录 Dubbo 介绍Dubbo 入门使用一、Zookeeper 注册中心安装启动二、服务提供方三、服务消费方 Dubbo 介绍 dubbo 2.x版本官方文档 参考 Apache Dubbo 是一款 RPC(Remote Procedure Call 远程过程调用)服务开发框架,提供了远程调用方案和…

RabbitMQ死信队列详解

什么是死信队列 由于特定的**原因导致 Queue 中的某些消息无法被消费,**这类消费异常的数据将会保存在死信队列中防止消息丢失,例如用户在商城下单成功并点击支付后,在指定时间未支付时的订单自动失效死信队列只不过是绑定在死信交换机上的队…

为什么谷歌每年向苹果支付180亿美元“保护费”

在大众印象里,谷歌和苹果似乎处处“水火不容”。 两大科技巨擘在各类产品和服务上竞争,比如操作系统、浏览器、地图、数字助理、手机,数不胜数。但是在这种敌对关系背后,却有着对他们双方都有利的秘密伙伴关系。 你或许不知道&am…

Qt 数据库QSqlDatabase使用记录

记录一些在QT中使用QSqlDatabase操作数据库时,需要注意的地方 创建数据库 bool CDBOperatorAbstract::_openDBConn(CDatabaseConfig config) {QWriteLocker locker(&m_locker);QSqlDatabase db;if(QSqlDatabase::contains(m_connectionName)){db QSqlDatabas…

CloudFlare 优选ip 和 优选域名的获取方法

1.CloudFlare优选IP网站:【链接直达】 2.CloudFlare 优选IP工具:【开源软件】 3.CloudFlare 优选域名:【GitHub开源工具】 4.CF优选域名推荐: time.cloudflare.com shopify.com time.is icook.hk icook.tw ip.sb japan.com malaysia.com rus…

深入学习《大学计算机》系列之第1章 1.2节——问题描述与抽象

一.欢迎来到我的酒馆 第1章 1.2节,问题描述与抽象。 目录 一.欢迎来到我的酒馆二.问题描述、抽象与建模1.什么是抽象2.为什么要抽象3.什么是建模4.建什么模 三.面向计算机的问题分析四.总结 二.问题描述、抽象与建模 什么是抽象?为什么要抽象&#xff1f…

Chrome限制第三方Cookie:未来无法再追踪你看过哪些敏感的“色色”内容了

当我们在浏览网络的时候,常听到「Cookie」这个词,但许多人可能不太清楚它到底是什么。最近,Google 宣布了一项重要更新,Google Chrome 将减少对第三方cookie 的支持,以提高用户隐私保护。 下面我会解释一下这个改变对…

打印机设置发票收据打印

由于各种打印机型号不一样,设置方式打印效果出入也很大,存在打印不全问题,发票右侧小数点后面的数字打印不出来、位置靠上下左右登问题,比较通用的设置方式如下: 首先找到控制面板,找到设备和打印机 进入到…

Aurora8B10B(二) 从手册和仿真学习Aurora8B10B

一. 简介 在上篇文章中,主要结合IP配置界面介绍了一下Aurora8B10B,这篇文章将结合文档来学习一下Aurora8B10B内部的一些细节 和 相关的时序吧。文档主要是参考的是这个 pg046-aurora-8b10b-en-us-11.1 二. Aurora8B10B内部细节 在手册上,对…

弧形导轨的精度等级

为符合工控自动化生产制造必须,弧形导轨在运输武器装备领域应时而生,并已在电子生产制造、手机上、半导体材料、动力锂电池等领域获得广泛运用。其中,弧形导轨的精度等级是评估其运动精度的重要指标,通常包括制造精度和运行精度两…