最近翻阅了一些软件工程原理相关的书,联想自己的搬砖之路,略有所悟,成文一篇,以作记录。
学习设计模式
很多人最初学习设计模式的时候,可能看的都是类似百科全书的设计模式书(我觉得这种书并不适合用来学习,不过用来做参考书是不错的选择,学习的话推荐BOB大叔的敏捷软件开发原则、模式与实践),看这种百科全书就会造成一种割裂,如同学习英文只看单词表一样,遇到句子结果不知道整句是什么意思,写代码时对于初学者来说可能只会生搬硬套设计模式,甚至到真正使用设计模式的时候发现自己已经全然忘记,脑袋空空。这样既花费了宝贵时间,还没有取得良好结果。
我的感悟是:写代码要有追求(模块化、松耦合),这样自然会有设计模式。为什么呢?这里简单讲下我自己的感受。我最早没看过什么设计模式,只是知道有这个东西,听名字感觉很高大上,心里犯嘀咕,这东西是不是很复杂,是不是很难学。看过之后,才发现其实设计模式是优秀代码中相当朴素的存在,只要你在写代码时有追求,或多或少都已经使用过这些设计模式,只是没有将他们总结成理论而已,设计模式其实存在于每一个追求良好架构的代码中,即使你从来不知道什么是设计模式。
抽象设计模式本身
优雅使用设计模式的代码自然遵循着面向对象设计原则,而设计模式是实现面向对象设计原则的具体实践。现在我尝试去抽象设计模式本身,具体抽象方式是根据面向对象设计原则和设计模式的相关特点,提取相应关键字,看看设计模式到底有没有什么共同特征,我称这个过程为抽象设计模式本身。OK,我们开始吧。
面向对象设计原则举例
先简单看几个核心的面向对象的设计原则:单一职责、开放封闭、依赖倒置、接口隔离、稳定依赖、稳定抽象。我们仅简单介绍其中三个原则:
- 单一职责:就一个类而言,应该仅有一个引起它变化的原因。
A和B都依赖C,并且A和B的业务变化都可能单方面导致C的修改,而且C中包含A或者B所不需要的接口,这就导致两个问题:1,A或者B引入了本来不需要依赖的接口;2,假设修改A的业务导致C要修改,那B就很无辜的受到了波及。单一职责目的是分离接口,解除耦合,消除不必要依赖
- 开放封闭:软件实体(类、模块、函数等)应该是可扩展的,但是不可修改。
开放封闭,这个太熟悉了,策略模式、模板方法典型的符合开放封闭原则,稳定不变的核心算法抽象出来(对修改封闭),变化的通过继承子类实现(对扩展开放,增加新功能只新增子类),核心是针对接口编程,即为面向对象的继承
- 依赖倒置:抽象不应该依赖于细节
依赖倒置核心思想是接口属于用户类,而不属于子类,用户决定接口的抽象行为,而不是依赖具体类
至此,虽然仅列出三个设计原则,但是貌似已经足矣,我们提取出其中出现过的关键词:
抽象、稳定、不变、消除依赖、解除耦合、变化、具体、继承
设计模式举例
提取出面向对象设计原则的关键词后,我们再看几个设计模式:
策略模式、模板方法、包装器、代理模式。
这几个模式网上有铺天盖地的资料,这里不详细说明,只针对他们使用到的面向对象技术进行抽象:
- 他们都是针对接口编程的,也即是针对抽象编程的,抽象是什么,抽象就是不变和稳定的东西
- 他们都包含继承与委托,继承不多说,委托就是自身引用别的对象,实际的工作让别的对象干就是委托
- 策略模式和模板方法都使用到多态
我们再统计下设计模式中出现的关键词:
针对接口编程、抽象、不变、稳定、继承、委托、多态
设计模式与代码
上面抽象出了很多关键词,而设计模式从代码层面看,以java为例:本质就是接口、抽象类以及委托和封装,绝大多数复杂模式都是使用这四样构造起来的,所以?设计模式是不是so easy?当然,在使用这四样技术时,一定要考虑消除依赖以及针对接口编程,针对接口编程本质就是针对稳定的抽象层编程
设计模式与框架
通常来讲,很多编程初学者都会觉得框架高大上又很神秘,那么我们现在就来戳穿它吧,框架其实也没什么了不起。运用以上总结的所有关键词,我们尝试描述一下什么是框架:
框架是稳定不变的抽象层,框架消除了业务类与框架层的依赖与耦合,让我们可以针对接口编程,通常只需要通过继承框架提供的某些接口类,便可以使用框架的相关功能,框架本质是通过将功能委托给我们实现的接口类来执行真正的业务。
所以,看看吧,框架是什么?框架就是高度稳定且抽象的代码而已,只是它更通用,因为它是遵循面向对象设计原则和实施具体设计模式写出来的代码,这些代码,我们称之为框架。举一反三,我们可以看看Spring做了些什么,K8S又做了些什么,Spark做了些什么,Docker又做了些什么,这些所有的通用软件或者框架,他们无不例外地全部使用以上规则抽象出了他们要实现的代码,最终这些稳定不变的抽象实现成为通用组件,从而供广大用户使用。
如何更好的实践设计模式
- 测试驱动开发:测试驱动开发会促使产生良好的设计,最简单的例子,如果一个类或者函数要具备可测试性,那么一定要解耦,划分边界,这会推动我们针对接口编程;如果一个工程难以测试,那么它的设计绝对超烂(具体测试驱动开发的资料非常多,读者可以自行筛选)
- 重构:重构本来也是测试驱动开发的一部分(红灯绿灯重构),在本文中单独拿出来说说,一般来说,代码不是一开始就写好的,而是重构出来的,消除代码臭味的过程就是应用设计模式的过程(具体可以参考老马的重构一书)
- 应用之前提取的关键词
忘掉设计模式
通过之前提取的一系列关键词,我们也已经抽象出了设计模式核心思想:
使用继承和委托消除依赖,解除耦合,尽量依赖稳定不变的抽象层(稳定抽象则不容易改变,一般为底层架构),整体软件则是越往上层越具体,越往下层则越抽象。
所以? 我们是不是已经可以忘掉那些乱七八糟的设计模式了?(只是开个玩笑,但是遵循上面总结的这句应该已经可以自行创造新的设计模式了。笑)
多实践
Practice makes perfect,不要杠,这绝壁是真理。多实践的意思绝对不是写更多的代码,而是:
- 多思考(自己如何漂亮的解耦)
- 多看好代码(看别人如何漂亮的解耦)
结尾
大家可以把这篇文章题目当做一个噱头,并不是提倡完全忘掉设计模式,而是希望所有人都能无招胜有招。最后,我们看看张无忌是如何学会太极剑法的(另,本人是金庸粉丝,倚天屠龙记看过不下40遍):
第二十四章 太极初传柔克刚
张无忌不记招式,只是细看他剑招中“神在剑先、绵绵不绝”之意。张三丰一路剑法使完,竟无一人喝彩,各人竟皆诧异:“这等慢吞吞、软绵绵的剑法,如何能用来对敌过招?”转念又想:“料来张真人有意放慢了招数,好让他瞧得明白。”
只听张三丰问道:“孩儿,你看清楚了没有?”张无忌道:“看清楚了。”张三丰道:“都记得了没有?”张无忌道:“已忘记了一小半。”张三丰道:“好,那也难为了你。你自己去想想罢。”张无忌低头默想。过了一会,张三丰问道:“现下怎样了?”张无忌道:“已忘记了一大半。”
周颠失声叫道:“糟糕!越来越忘记得多了。张真人,你这路剑法是很深奥,看一遍怎能记得?请你再使一遍给我们教主瞧瞧罢。”张三丰微笑道:“好,我再使一遍。”提剑出招,演将起来。众人只看了数招,心下大奇,原来第二次所使,和第一次使的竟然没一招相同。周颠叫道:“糟糕,糟糕!这可更加叫人胡涂啦。”张三丰画剑成圈,问道:“孩儿,怎样啦?”张无忌道:“还有三招没忘记。”张三丰点点头,放剑归座。张无忌在殿上缓缓踱了一个圈子,沉思半晌,又缓缓踱了半个圈子,抬起头来,满脸喜色,叫道:“这我可全忘了,忘得乾乾净净的了。”张三丰道:“不坏,不坏!忘得真快,你这就请八臂神剑指教罢!”
网友评论