图解设计模式,看完秒懂!!!

点击关注公众号,实用技术文章及时了解

图解设计模式,看完秒懂!!! 图解设计模式,看完秒懂!!!

在这个软件发展日新月异的时代,软件产品推陈出新应接不暇,软件需求更是变化莫测,难以预判。作为技术人员,我们在软件开发过程中常常会遇到代码重复的问题,这就不得不对系统进行改动、重构,所以良好稳固的软件架构就显得至关重要。设计模式正是为了解决这些问题,它针对各种场景提供了最适合的代码模块复用解决方案。

设计模式最早于1994年由Gang Of Four(四人小组)提出并以C++面向对象语言作为示例,如今大量应用于Java、C#等面向设计语言所开发的程序中。其实设计模式和编程语言是无关的,编程语言只是与计算机沟通的媒介,它们都可以用自己的方式去实现设计模式。从某种意义上讲设计模式并不是某种具体的技术,而更像是一种思想,一种格局,本书将以时下最流行的Java面向对象编程语言为例,对23种设计模式逐一拆解分析。

在学习设计模式之前我们得先搞清楚到底什么是面向对象。我们都生活在现实世界里,这里充满了各种对象,如本章封面图所示,其中的山川河流、花鸟鱼虫、高楼大厦、车水马龙,我们每天都要面对他们,与他们沟通、互动,这是对面向对象最简单的理解。为了将现实世界重现于计算机世界中,我们想了各种方法针对这些对象建立数字模型(类),但是理想很丰满而现实很残酷,我们永远也无法包罗万象这大千世界中的万事万物。而当人们在“造物”过程中发现其实类与类之间有着千丝万缕的关联,于是想到面向对象特有的编程方法,利用封装、继承、多态的方法去建模,大量的减少了重复代码、降低类间耦合,像拼积木一样组装了整个“世界”。“封装”、“继承”和“多态”就是面向对象的3大特性,这些都是设计模式的基石,我们必须要理解掌握。

1.1 封装

对于封装的概念,我们就以现实世界中的事物举例,比如胶囊对于各类药物混合的封装;钱包对于现金、身份证及银行卡的封装;电脑机箱对于主板、CPU及内存等零件的封装等等,封装可以说在我们生活中比比皆是、随处可见。我们举一个现实生活中最常见的例子,我们都用吸管喝过饮料吧,如图1-2所示。

图解设计模式,看完秒懂!!!
图1-2 电脑主机类图

其实封装的理念在历史发展中非常多见,其实它就是随着时间的推进对前人经验技术产物的逐渐堆叠组合的过程。举个例子,早期的枪设计非常原始简陋,打一发子弹要很长时间去准备,装填时要先把火药倒入枪管内,然后装入铅弹,最后用棍子戳实后才能发射,而发射后还要再循环往复进行装填这一过程,耗时费力。为了解决这个问题,人们开始了思考,既然弹药装填困难,那么不如把弹头和火药组合起来然后封装在弹壳里。这样只要撞击底火弹头就会被爆炸的火药崩出去,装入枪膛一触即发,如图1-3所示。

图解设计模式,看完秒懂!!!
图1-4 生物的遗传基因

儿子从父亲那继承下来一些东西,不需要自己再去拼搏了,避免重复造轮子,比如富二代继承家产,生来家财万贯;再比如天生一副好嗓子,因为妈妈是歌星。所以不管是身体上还是财富上,继承能让子孙后代得到父辈基业的传承。以我们最常见的动物举例,狗是人类最忠实的朋友,它们在一万多年的演变过程中不断繁衍,再加上人类的培育诞生了许多各色各样的品种,如图1-5所示。

图解设计模式,看完秒懂!!!

如代码清单1-1所示,我们为犬类定义了品种、性别、毛色、年龄4个属性,并且带有响应的setter和getter方法,还有第12行的吠叫方法,这也是所有犬类品种的共有行为,统统都能被子类继承。需要注意的是,倘若我们把犬类属性的访问权限由“protected”改为“private”,这就意味着子类不能再直接访问这些属性了,但这并无大碍,最终其依旧可以通过继承下来的并且声明为“public”的getter和setter去间接访问它们,总之能达到继承的目的即可。好了,接下来我们用子类哈士奇犬来说明如何继承,请参看代码清单1-2。

代码清单1-2 哈士奇类Husky

如代码清单1-2所示,为了延续父类的基因,哈士奇类在第一行的类定义后用“extends”关键字声明了对父类Dog的继承关系。第3行构造时以“super”关键字调用了父类的构造方法,并初始化了狗的品种breeds为“哈士奇”,当然年龄一并会被父类初始化为0岁。我们可以看到哈士奇类的代码已经变得特别简单了,并没有定义任何getter或setter方法,也没有出现犬吠方法的定义,而当我们调用这些方法时能神奇般地得到结果,自然而然地,它沿用了父类的方法。只是单单继承父类的本领还是不够的,哈士奇类更应该有自己的特色,比如增加自己的属性、方法,可以看到代码第7行我们增加了哈士奇特有的“拉雪橇”本领,这是父类所不能及的。除此之外,哈士奇吠叫起来比较特殊,可能是基因突变或者是返祖现象导致,这时我们甚至可以重写吠叫方法让它发出狼的叫声。接下来其他的子类继承各尽其能,比如贵宾犬可以作揖,藏獒可以看家护院等等,读者可以自己发挥。总之,继承的目的并不是一成不变的全盘照搬,基于父类的基因,子类更可以灵活扩展。

扩展阅读

大家都知道任何类都有一个toString()方法,但我们根本没有声明它,这是为什么呢实这就是从Object类继承下来的优良传统,因为Object是一切类的祖先类

1.3 多态

众所周知,在我们创建对象的时候通常会再定义一个引用指向它以便后续进行对象操作,而这个引用的类型则决定着其能够指向哪些对象,用犬类定义的引用绝不能指向猫类对象,所以说对于父类定义的引用只能指向本类或者任何子类实例化出来的对象,这就是一种多态。除此之外还有其他形式的多态,例如抽象类引用指向子类对象,或者接口引用指向实现类的对象。

我们继续以上一节中的犬类继承为例,如果以犬类Dog作为父类,那么哈士奇、贵宾、藏獒、吉娃娃等等都可以作为其子类,如果我们定义犬类引用dog,那么它就可以指向犬类的对象,或者其任意子类的对象,翻译成大白话就是“哈士奇是犬类,藏獒是犬类……”。下面我们用代码来表示,请参看代码清单1-3。

代码清单1-3 犬类多态构造示例

如代码清单1-3所示,前3行都没有任何问题,犬类引用可以指向狗,也可以指向哈士奇,这让dog引用变得更加灵活、多变,可以引用任何本类或子类对象。然而第5行代码就会出现问题,让哈士奇的引用指向犬类Dog的对象就行不通了,这就好像是说“犬类就是哈士奇”一样,逻辑混乱。

再进一步讲,多态其实是利用了继承(或接口实现)这个特性体现出来的另一番光景。我们以食物举例,中华美食博大精深,菜品众多且色香味俱全,这都离不开各种各样的食材,如图1-6所示。

图解设计模式,看完秒懂!!!
图1-7 人类与食物类图

我们在设计的时候,对多态的把握一定要适可而止,切勿无限放大,否则通通用Object作为引用不就更加灵活,多态性更加丰富吗以说物极必反,过于灵活的自由散漫会有失规范性,无规矩则不成方圆,越泛化不代表越好,适可而止才是最好的。

1.4 电脑与外设

为了更透彻深入地理解面向对象的特性,以及设计模式如何巧妙利用面向对象来组织、布局各种模块协同工作,我们以一个形象贴切的例子切入实战部分。如图1-8所示,相信很多读者都没有见过这种电脑,没错,这是一台早期的个人电脑,可以明显看到它的键盘、主机和显示器等都是集成为一体的。

图解设计模式,看完秒懂!!!
图1-9 现代电脑设计

我们每天都在接触电脑,但对于这种设计可能从未思考过,为了便于理解我们让电脑和各种设备鲜活起来,下面是它们之间展开的一场精彩对话,其中角色包括一个电脑类,一个USB接口,还有各种USB设备类,故事就这样开始了。

电脑:“我宣布,从现在开始USB接口晋升为我的秘书,我只接收它传递过来的数据,谁要找我沟通必须通过它。”

USB接口:“要接驳我的设备是什么我不关心,但我规定你必须实现我定义的readData(Data data)这个方法,但具体怎样实现我不管,总之我会调用你的这个方法把数据读过来。”

USB键盘:“我有readData(Data data)这个方法,我已经实现好了,传过去的是用户输入的字符。”

USB鼠标:“我也一样,但传过去的是鼠标移动或点击数据。”

USB摄像头:“没错,我也实现了这个方法,只是我的数据是视频流相关的。”

USB接口:“无所谓你们是什么类型的数据,只要传过来转换成Data就行了,我接收你们的接驳请求,除了PS2鼠标。”

PS2鼠标:“@电脑,老大这怎么办找来这个USB接口太霸道了,我们根本无法沟通,你们都不能尊重一下老人吗

Computer电脑:“你自己想办法,要顺应时代潮流,与时俱进。”

PS2鼠标:“……”

显然,通过这场对话我们有了更深刻的认识,电脑中封装了一个USB接口,这就是“封装”,而键盘、鼠标及摄像头都是USB接口的实现类,广义上理解这就是一种“继承”,所以最终电脑的USB接口就能接驳各种各样的USB设备的,这就是“多态”,我们来看它们的类结构图,如图1-10所示。

图解设计模式,看完秒懂!!!

另外,随机送出5本,抽奖即可,明天中午12点开奖,中奖者把收货信息及时写入,三天内发出!

图解设计模式,看完秒懂!!!

来源:Java知音_

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2021年6月16日
下一篇 2021年6月16日

相关推荐