设计模式(四)结构型模式

前言

结构型设计模式,主要研究:

  • 主要有哪些场景使用结构型设计模式;
  • 每种场景应该使用何种设计模式;
  • 以程序中的功能为核心,研究程序功能的组织结构。所以这一章,我们要把“功能结构”作为研究的核心。

下面分别对几种结构型模式加以说明。

1. 适配器模式

示例:适配器模式

使用场景

想要在系统中添加某个功能,类似的功能在其他项目中已经实现,而且经过分析,旧的接口可以经过适当的封装,转换成新的适用于当前系统的接口。这样可以最大程度地复用已有的模块。

原理

通过适配器将已有功能的旧的接口,转换为新的接口,从而实现使已有的功能为新的系统服务的目的。

不适用的情况

以下情况下,不要使用适配器模式:

  • 旧的接口无法转换成新的接口;
  • 写适配器的工作量几乎可以重写所需的功能时。
使用须知

适配器模式其实是一种取巧的做法,在使用时需要慎重考虑。已有功能通过适配器集成到新的系统后,如果出现问题或者需要进行功能扩展,其维护成本是一个需要考虑的问题。例如,已有功能是否使用了过时的技术,或者资料不全,都可能成为项目的风险所在。

本质

适配器模式本质上是通过将一接口封装成另一种接口,实现了模块功能复用。

2. 桥接模式

示例:桥接模式

使用场景

桥接模式是少用继承,多用组合的第一例。
拿菜鸟教程中的例子来说,假如我们现在要实现圆类,包括红色圆和绿色圆两种圆。
首先容易想到的方法是,先写一个圆基类,并添加一个虚(virtual)的绘制函数。然后分别派生出红色圆类和绿色圆类,在子类中分别重新实现绘制函数,将圆绘制成指定的颜色。
在这种简单的例子中,使用继承是没什么问题的。但是假如圆基类还有一个虚函数,此虚函数用于对圆进行旋转。旋转分为两种,顺时针和逆时针旋转。我们想要四种类型的圆:

  • 顺时针旋转的红色圆
  • 顺时针旋转的绿色圆
  • 逆时针旋转的红色圆
  • 逆时针旋转的绿色圆

如何使用继承来实现呢?难道要派生出四个子类吗?如果还有其他功能组合呢?要多少个类呢?这样下去无疑会导致“类的数量爆炸”问题。

原理

结构型模式是研究程序功能组织方法的设计模式。当程序中需要对几种功能相互组合时,应该用组合,不要用继承。
桥接模式下,对于每个功能,应该提取出一个接口类,这个接口类可以有不同的实现。而代表不同的功能接口,可以作为主体类(此例中为圆类)的成员变量,放在一起。需要什么功能,就new哪种接口子类,保存在接口变量中,这样就可以把不同的功能组合起来。
这样一来,类的数量会保持在最低水平。

相对于继承,桥接模式相当于把主体类中的每个虚函数都单独提取出来,构成 一个接口类。这个接口类连接了具体实现和主体类,所以这个模式叫桥接模式。这个名字其实不是很能反映此模式的内涵,其实叫“功能组合模式”更为贴切。

可能有的小伙伴会说,上面的功能其实用C语言实现不是更简单吗?

  • 用一个结构体代表圆,有半径、边框宽度等属性;
  • 每种功能就是一个函数,参数为圆的结构体。

这不就完成了吗?是的!
这个场景下,确实使用C语言实现更简单,不需要使用C++面向对象的任何特性即可实现。可以看出,C++的面向对象的特性,并不是万能的,并不是在所有情况下都是最优的,甚至有时候不如C语言简单直接。从另一个角度说明,大家在面向对象编程的时候,不要把自己的思维局限于面向对象,面向对象思想在一些时候,是不如面向过程的,甚至会把功能结构复杂化,设计到最后导致代码难以维护都是有可能的。

使用须知

桥接模式会导致代码中存在设计模式的代码,会增加代码的理解难度。相对来说,积极作用还是远大于副作用的。

本质

桥接模式的本质是:

如果项目中出现了功能组合的场景,使用继承封装功能是错误做法,要把功能单独提取出来分别封装好以后,再进行组合。


3. 过滤器模式

示例:过滤器模式

使用场景

现有一组对象,我们想要根据不同的过滤条件,筛选出符合条件的一部分对象。

一般写法

最简单粗暴的方法是,在需要进行筛选过滤的地方,直接遍历对象数组,在循环体内进行条件判断。这种写法的优点是简单直接,缺点是如果有多个地方需要使用筛选过滤功能,则需要在多个地方编写重复的代码,这会降低代码的复用性和可维护性。

推荐写法

使用过滤器模式,把筛选功能封装起来使用即可。接口也很好定义,输入对象数组,输出符号条件的对象数组。

本质

过滤器模式的本质是:

当需要从一组对象中过滤出一部分符合条件的对象时,可以考虑将每种过滤功能都封装为一个类,提高代码复用性和可维护性。

4. 组合模式

示例:组合模式

组合模式是一种树形的对象组织结构,在建造者模式已有相关说明,这里不再赘述。

5. 装饰器模式

示例:装饰器模式

使用场景

装饰器模式的研究对象有两个:

  • 已有功能
  • 扩展功能

当我们需要扩展一个类的功能,但是又不想直接在此类上进行改动时,一般的做法是使用继承来实现。继承出来的子类具有父类的属性和方法,在父类基础上可以添加新的功能。
除了继承,还可以使用装饰器模式。装饰器模式是指,新建一个扩展类,将被扩展类的对象作为扩展类的成员变量保存,在扩展类中,操作被扩展类,实现新的方法和功能。
简单来说,装饰器模式就是新建一个类把已有类的功能包装起来,实现新的功能。

使用须知

装饰器模式和继承各有优缺点,使用时要加以权衡,选择最优的方案。

本质

从本质上说:

装饰器模式通过将已有功能作为成员变量整个封装(包装)起来,扩展的新功能,和已有功能耦合最小,互不影响。

6. 外观模式

示例:装饰器模式

本质

这个模式比较简单不再赘述。其本质是:

将已有功能封装起来,提供更易于使用的接口,屏蔽更多实现细节,等于是加了一个中间层。

7. 享元模式

示例:享元模式

按照我们的分类,此模式应该属于创建型模式。它是借助工厂模式来实现一个对象缓冲池,减少对象数量 ,加速创建速度。这里不再赘述。

8. 代理模式

示例:代理模式

应用场景

代理模式就是中介模式。例如我们想要租房,原本租房是发生在租客和房东之间的事务,但中介的出现,虽然会有一定的费用(损耗),但是整个过程的推进会更加顺利。代理模式,用来将两个比较难以直接沟通的功能主体关联起来,实现二者交互。

使用须知

和租房找中介一样,只有在必要的时候才找,否则就是浪费资源,只有在非用不可的时候才建议使用代理模式。

本质

代理模式的本质是:

代理模式封装了沟通所需的所有功能,将两个难以直接沟通的功能主体连接起来,起到了桥梁作用。


结语

结构型模式,就是以功能为核心,研究功能转换、功能调用、功能组合、功能封装等各种情形下,将哪些功能封装到哪些类中,更加高效地实现需求,提升代码的可维护性。

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

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

相关文章

centos 删除crontab_centos下crontab的使用

4.cron文件语法:分 小时 日 月 星期 命令0-59 0-23 1-31 1-12 0-6 command (取值范围,0表示周日一般一行对应一个任务)5.记住几个特殊符号的含义:“*”代表取值范围内的数字,“/”代表”每”,“-”代表从某个数字到某个数字,“,”分开…

【转】GitHub客户端操作1--仓库相关操作github团队协作流程

1、创建仓库 点击“”,点击Create,然后填写Name为my,点击Create repository,即可创建一个my仓库 2、从本地仓库存放位置,添加test仓库到GitHub客户端 点击“”,点击Add,然后点击Browse,选择仓库存放位置&a…

音视频相关链接

开发库 FFmpeg FFmpeg官网 FFmpeg github 平台相关 DirectShow DirectShow简介 DirectShow官网

【转】GitHub客户端操作2--分支操作

简单分支操作 (1)创建新分支:my分支 备注:新创建的分支:my分支里面的内容是和master分支里面的内容是完全一样的。 (2)删除my分支 (3)修改my分支【在my分支上进行项目内…

uniapp动态修改样式_uniapp样式动态绑定

场景一:用户点击按钮后动态切换按钮选中样式(如图)已上线未开始//选择状态selectState(e){this.whichSelectede.currentTarget.dataset.state}.state-btn-content{//write your style.state-btn-selected{ ... }.state-btn-noselect{ ... }}注:需要注意的…

音视频工程师(初步)(一)音视频的基本概念

1. 前言 本文是音视频工程师系列的第一篇文章。 学习音视频的过程中发现,网络上高质量的音视频技术博客不是很多。具有代表性的是 雷神的 雷霄骅的CSDN博客 因为笔者是一名普通的软件开发人员,一向不喜欢高高在上或者晦涩难懂的理论,我们…

【转】GitHub客户端操作3--pull Request(拉请求)

一、参考说明 参考文章一:Github上提交代码(pullrequest) 网址: https://jingyan.baidu.com/article/358570f64dcdc2ce4724fc32.html 参考文章二:GitHub——Pull Request 网址:http://blog.csdn.net/u012325167/article/detai…

webstorm 内存溢出怎么弄_webstrom 内存溢出,软件崩溃卡死解决的方法

今天用gulp搭建了一个工程,准备做一个体育h5的项目,其中需要用到sass代码压缩,加版本号等功能.gulpfile.js和package.json都是已经写好的.我用CMD命令窗口cnpm安装node_modules依赖文件.当我安装完毕之后用webstrom打开时,第一件事先把node_modules排除忽略了.如下:然后我去编辑…

躺平也要看,2022年计算机相关考试汇总

1. 全国计算机专业资格考试(软考) 1.1 官网 全国官网:https://www.ruankao.org.cn/,从全国官网首页的底部可以直达各个省区的考试机构报名网站。 1.2 考试安排 软考一年两次。 场次报名时间考试时间上半年 预计报名时间在2月…

【转】GitHub上README.md教程

本文是转载文章,文章的来源:csdn博客 博主:果冻虾仁 文章: GitHub上README写法暨GFM语法解读 博文地址:https://blog.csdn.net/guodongxiaren/article/details/23690801 转载请保留原作者guodongxiaren的原文地址&…

python supervisor flask_supervisor配合uwsgi部署flask应用

这已经是第N次来部署flask应用了, 但是每次都花了不少时间在配置上面, 这里一次性记录下, 备个忘~写在前面其实使用uwsgi来部署flask应用在官网上已经有较为详细的 文档 了, 推荐先读一下.先解决一些问题:为何使用 uwsgi 来部署应用? 方便管理; 较为常见的部署方式; 可配置性较…

设计模式(五)行为型模式

前言 在上一篇结构型模式中,我们以功能为基本单位,研究了一些设计模式,用于实现功能转换、功能组合、功能封装等目的。 我们知道,面向对象编程有两个核心元素:对象、对象间通信协作。从面向对象的角度看,…

51单片机auxr寄存器_51—52系列单片机特殊功能寄存器一览表

P2.1P2.0RSTP3.0/RXDP3.1/TXDXTAL2XTAL1P3.2/INT0P3.3/INT1P3.4/T0P3.5/T1GNDVCCP1.7P1.6P1.5P1.4P1.3P1.2P1.1/AIN1P1.0/AIN0P3.7注:类似的还有Philips公司的87LPC64,20引脚8XC748/750/(751),24引脚8X749(752),28引脚8XC754&…

【转】WPF单位真的与分辨率无关吗?

转载自http://www.cnblogs.com/helloj2ee/archive/2009/04/21/1440709.htm WPF从发布之日起,一直将“分辨率无关(resolution independence)”作为其亮点,声称使用WPF制作的用户界面在轻巧的Ultra-Mobile PC的屏幕上和在50英寸的电视机上都能很好地显示。…

设计模式(六)J2EE 模式

前言 本章设计模式只挑了一些必要的加以讲解,因为有的设计模式过于简单或者根本用不到,可以不做了解。 MVC 模式 使用说明 MVC模式可以说是最有名的设计模式之一。它提出将软件的数据模型Model、视图Visual、控制器Controller三者分开封装&#xff0c…

ubuntu设置始终亮屏_ubuntu设置关闭屏幕和锁定

见链接:http://askubuntu.com/questions/177348/how-do-i-disable-the-screensaver-lockIf you want to wrap your app in a script that takes care of this for you when you launch it (or GUI simply isnt an option), the best command-line solution as of Ub…

【转】世上最简单的vue教程

一、需要了解的基本知识 node.js Node.js是一个Javascript运行环境(runtime),发布于2009年5月,由Ryan Dahl开发,实质是对Chrome V8引擎进行了封装。Node.js对一些特殊用例进行优化,提供替代的API,使得V8在非浏览器环境…

工程师学乐理(一)尝试理解音乐

前言 很早就接触了乐理,但是一直没有学懂,越学问题越多。个人感觉,其中很大的原因是有关教材写得看不懂,用未知的东西描述未知的东西,不知所云。前几年还买了一把吉他,买了课程,断断续续学了几…

【转】Vue.js入门教程(一)从静态页面到前后端分离开发

第一章:基础知识 我能看懂吗? 只要你现在能用htmlcssjs制作一个静态页面,相信我,你100%可以读懂这篇文章。 本文尤其适合那些想要了解前后端分离开发技术,或者刚刚脱离传统MVC开发模式的前端人员。 回想一下&#xf…

vuebaidumap 删除覆盖物_VUE BAIDU MAP覆盖物 - 自定义覆盖物手记

前言覆盖物的最高级就是自定义覆盖物,而往往业务中就必须用自定义覆盖物,因为都用上了地图这么吊的组件了,覆盖物也必须华丽、高度定制。官网Github自定义覆盖物手册效果效果核心其实是三角箭头的阴影,其他都很好说。说起三角的阴…