“抄袭来的” 设计模式
“请问你开发中使用过设计模式吗?”
“能说一下工厂模式如何实现吗?”
“请问Spring 使用了哪几种设计模式?”
上面这些问题是不是很熟悉?想必大家面试都被问过。还记得我第一次被问到时的一脸懵逼。随后立刻被对面投来的鄙夷眼神一万点暴击。 铩羽而归后,一口气学完23种设计模式。不禁连连感叹:代码还可以这么写!!
接下来的日子里,即使是写hello world,我也会问自己:“你知道有23种写法吗?”。 现在想想真的是 too young! too simple!
从生搬硬套到灵活运用,我体验过设计模式的甜,也尝过过度设计的苦。但是不可否认,设计模式一定是一把利刃。虽然使用不当也会砍伤自己。
在某个撸完码的清晨,品了一口保温杯中的枸杞,看着窗外凌晨四点的帝都,脑海里忽然闪现一个拷问灵魂的问题:设计模式从哪里来?
无处不在的模式
建筑学家 Christopher Alexander 说过:每一个模式都描述了一个在我们周围不断发生的问题,以及该问题解决方案的核心。这样,你就可以一次又一次地使用该方案而不必做重复的劳动。
这句话说的太通用了,放到软件领域完全适用啊!如果不了解 Alexander,没准以为这是哪位计算机领域的大神呢!
模式是解决问题的方案总结。无论在什么行业、什么界,不管软的、硬的。只要问题相似,都可以用类似的方案解决问题。
模式拥有如下四种要素: 问题:
设计模式是用来解决问题的。没有问题乱用什么设计模式?这是赤果果的炫技!
所有的模式都是用于解决某种共性问题,所以先有问题才会有模式。问题描述了设计模式所能解决的问题。问题可能是不灵活的设计方式,也可能是难以实现的功能。
解决方案:
解决方案描述设计的组成部分。各个对象或者组件间的关系和职责。解决方案是灵活的,并且通用于一类问题。当遇到类似问题时,都可以采用此种解决方案。
效果:
有句话叫“不看广告,看疗效”。设计模式也得对症下药,治标治本。
效果描述了采用此种设计模式可以为你带来的收益。某几种设计模式都可以为你解决同一个问题,但你需要权衡不同设计模式的效果,做到有的放矢。最终达到最好的灵活性、扩充性和可移植性。
名称:
每个设计模式都需要有一个简短的名称。有一个好记的名字,在需要的时候才能被想起来。通过名称也可以很快映射出此种设计模式的其他要素。
其实模式四要素和看病吃药是一回事。得了某种病是问题。解决方案是吃哪几种药,剂量是多少。效果当然就是药的疗效。最后要起个好名字。是 “对乙酰氨基酚” 好记,还是 “感康” 好记,这不言而喻。
来模拟现实世界吧
软件领域中遇到的问题,在人类文明几千年的发展过程中早就遇到过。并且也有相应的模式来解决。 软件设计模式基本上都是参照现实世界中已有的模式实现。
想一想,早上穿着“工厂”生产的衣服“装饰”一下自己。到公司取出电脑,插上“适配器”(电源),再接上鼠标、键盘、显示器 “组合” 成工作站。中午叫个美团 “代理” 购买午餐。下午困了,想睡一会,告诉同事如果经理来了,赶紧“通知”我。下午用公司 “模版” 完成汇报PPT。结束自己 “thread” 一天的工作,晚上美美的进入 “sleep”。但是,第二天早上…... 真的是充满设计模式的一天!
没个对象,都不好意思聊模式
谈到设计模式,就需要聊面向对象。可以说没有面向对象就没有今天的设计模式。 软件设计想要模仿和借鉴现实世界的模式,首先要具备映射现实世界的能力。面向对象正是解决了这个问题。运用面向对象,我们可以在软件世界构造现实中的一切,然后 "抄袭“ 现实世界已有的优秀解决方案。
面向对象可以让你程序设计和真实世界更契合,从更高的层次对系统建模。这会带来如下优点:
- 现实世界有几千年积累数以万亿计的优秀设计,无论是具体的机械设备,还是方法论,或者工程理论,甚至只是一个小技巧。我们都可以拿来作为软件设计的参考。
- 面向对象开发的软件,让开发者更容易理解。我们每个人都熟知我们所生活的世界。甚至仅凭生活经验,就能猜出对象的某个行为逻辑是什么。
有了面向对象的利器,套用现实世界的设计模式,是不是23种软件设计模式立刻就应运而生了呢?
现实很残酷,设计模式在90年代初才被逐步重视起来,直到94年GOF集合23种设计模式出书。而面向对象语言在70年代就已经出现雏形,那么中间这二十年都干嘛去了?
找个对象还挺难的
我们先聊聊面向对象语言的发展史。 早在1967年就已经出现面向对象语言Simula 67。它拥有现在面向对象语言的基础概念。只不过由于实现不够完整,并且难以学习,最终没有流行开来。但是其面向对象的思想对后面软件语言的发展还是产生了深远的影响。
上世纪70年代出现的Smalltalk,被公认为是第二个面向对象的程序语言。并且是第一个完整实现面向对象的程序语言。它推动了面向对象的程序语言发展。它后面出现的C++,Java,C#,Ruby等,无不受其影响。此外90年代很多编程思想都来源于Smalltalk。
此后,经历 C++ 的辉煌以及借助 Java 语言便利性的有力推广,面向对象的程序语言开始大面积占领市场。时间来到90年代,GOF的《设计模式》将软件设计模式推到行业面前,经典就这样诞生了!
由此可以看到设计模式紧随面向对象语言的发展前行。从面向对象语言诞生之初,从业人员就已经开始不断总结解决问题的设计方案,通过模式的四要素进行提炼。虽然没有公布于众,但其实早已有了智慧的结晶,只是等一个契机迎来爆发。
设计模式就是面向对象的灵魂和智慧!
面向过程的语言就不配拥有灵魂和智慧吗?
文章读到这里,想必你肯定有这个疑问,面向过程的语言没有设计模式吗?
说到这个问题,我们先回到模式的定义上来----解决问题的核心方案。无论面向过程、还是面向对象,其实都是在解决软件领域的问题。面向过程的语言也需要可复用的解决方案。只不过这些方案没有集结出书而已。但是一定存在于某个人的文档里、博客里或者脑子里。
后来随着编程语言向面向对象语言倾斜,人们也更加关注面向对象语言的设计模式。《设计模式》这本书正是在这个时期推出并走红。另外一个最重要的原因,面向对象语言让我们可以很自然的映射现实世界,从而可以更加容易的使用其他领域已有的方案。
换句话讲,是面向对象让设计模式大量涌现,并且开始被从业者重视。因为通过面向对象,可以更容易的复用现实世界已存在的模式。但面向过程语言也有设计模式。
总结
面向对象让软件世界有能力和现实世界形成映射。从而,人类几千年积累的优秀设计和实践,可以被直接转化运用到软件之中。这对于只有几十年的软件行业,是跨时代的进步!!如果你阅读过大量开源软件代码,就会发现优秀的软件设计全部来源于生活。
当你面对一个软件难题,其实可以跳出来想一想现实世界中有没有类似问题,解决方案是什么。
我们只需要把现实世界造好的轮子搬到软件中即可。站在人类几千年的文明之上,还会有什么不能解决的软件难题吗?
模式是通用的,善用现实世界的模式解决软件问题,是优秀软件设计者必备技能。 后面系列文章,我会通过现实世界映射来分析软件中的优秀设计。归根溯源,一起看看这些优秀的软件设计从何而来!