胡琪

为今天工作,为明天投资,为未来孵化一些东西!

设计模式与架构

个人觉得设计模式的掌握重在对其应用场景和优缺点的理解,重在“形”而不在“义”。设计模式的定义和UML图只是辅助手段而已,因此本专栏的《设计模式》会花比较大的篇幅讲解各个设计应用场景以及各场景下的优缺点,同时对每个设计模式都会举1-2个知名的开源项目的示例,让大家更容易体会到这种设计模式往往用在哪些场合下。而不是像网上绝大部分讲设计模式的文章举几个自己按照UML图实现的代码示例,这种做法充其量只是在告诉你如何去实现这个设计模式而已,而不是告诉你为何要去用设计模式实现这段功能(本质上就是应用场景),意义不是很大。

【设计模式之】OOP六大基本原则与单例模式

【设计模式之】建造者模式

【设计模式之】工厂方法模式

【设计模式之】策略模式

【设计模式之】观察者模式

【设计模式之】代理模式与动态代理技术(JDK自带与CGLIB)

【设计模式之】适配器模式

我对设计模式的一点看法

关于设计模式,很多人觉得很难,各种抽象,各种解耦,像看天书一样不知所云,即使某些地方勉强看懂了,到了用的时候也不知道该在哪些场合下用;也有很多人觉得设计模式很简单,因为他们觉得能够看懂市面上的设计模式书中讲的一些小示例。而我的看法,设计模式难不难我不敢妄加定义,但是我敢肯定的是设计模式一点都不简单,这是我敢明确表态的结论。你只是看懂了设计模式的UML图,看懂了讲解设计模式的一些示例代码,这不是设计模式的真正意义所在,设计模式是一种思想,重在”形”而不在”义”,能够看懂那些示例代码不代表你学会了设计模式,个人觉得有且仅有一种方式表明你学会了设计模式,那就是在你写的代码中能够看到设计模式的影子,或者在一些明显应该使用设计模式的地方你使用了设计模式,亦或是你觉得自己根本没用啥设计模式但实际上达到了设计模式的效果。这也是设计模式真正的难点所在,该在哪些应用场合下使用哪种设计模式。

这也是设计模式区别于一些相对较难的东西的地方,比如llvm,比如插件化技术,设计模式它是一种思想,无任何固定实操,就像一句名言:懂无数的道理却依然过不好这一生,因为道理无法实操,因此你很难知道该怎么应用它,该在什么时候去应用它。只能靠自己去悟,靠不断的反思,尝试与反馈来升级你对它的认知。

而llvm也好,插件化也好本质上只是一个新的技能很多时候你觉得一个技能难是因为你缺少和这些技能相关的基础知识以及这些技能相关的子技能。对于任何技能而言个人觉得只要你肯花时间学习,学会它基本上是一件概率为100%的事情,唯一的差别只不过是你学会它要花费多长时间的问题。
这是我在工作中学习llvm后的最大感受。刚开始接触llvm时觉得有点难,一方面因为llvm是一个新的知识点,而自己在这个领域的基础知识基本为0,另一方面LLVM开发时做的很多操作本质上是类似用指令去完成函数的功能,类似汇编开发,而我们平时的开发逻辑都是编程语言的语句层面,因此它的思考模式和我们平常写代码是不大协调的,但是后面慢慢的摸索一段时间后发现刚开始觉得难的地方实际上没那么难。这就类似小时候学骑自行车一样,刚开始也会觉得很难,但是当你学会后会发现骑自行车也没那么难。这也是很多技能的一个特点:会者不难,只要你肯花时间钻研,学会它基本上是一件概率为100%的事情,唯一的差别只不过是你学会它要花费多长时间的问题,因为技能能够通过大量的实操训练,刻意练习来获得。这也是为何技术类岗位jd往往每一年要求的技能都会比上一年多很多的原因,因为技能本质上绝大部分人学会它的概率是100%的,唯一的差距就是时间的长短,学习能力强的同学学会某个技能时间花费会短一些,学习能力差一些的同学可能花费时间会长一些,但是一年的时间足以让绝大部分人学会很多技能了(就像小时候学骑自行车你可能学会它花费了几个月,别人花费了几个星期就学会了,但是从一年的维度来看,你们都学会了骑自行车),因此只能用一些更新的技能要求来拉开候选人的差距。也正是因为这个原因,所以学习能力较强的同学在单位时间内来看学会的技能数量是要多于学习能力差一些的同学的,最终日积月累可能就从量变到质变造成2者能力的差距了,这个时候的差距已经不仅仅是技能上的差距了。技能上的差距不是很可怕,毕竟闻道有先后,术业有专攻,每个人都有自己相对擅长和相对薄弱的技能,但是能力上的差距是一件非常可怕的事。如果你有幸能够接触到什么问题扔过来基本都能解决的人,你就会明白这句话的意思了。

而思想则不然,无法通过大量练习获得,因为它很难实操。对于设计模式而言你觉得简单的只是别人为了让你看懂而举的一些简单的示例而已。如果是一个超大型项目呢?你还能灵活的使用设计模式吗?思想和技能还有另外一个很大的区别就是技能很容易过时而思想不容易过时。比如安卓开发,llvm开发本质上都是一个技能,如果某天安卓像诺基亚那样被市场淘汰掉了(可能性比较小,技术上被取代的可能性存在,但生态上要完全被取代非常难,可参照linux系统和windows系统),如果某一天出现了一个更加强大的编译器架构取代了llvm(可能性比较小),那么你会的这些技能都将失去竞争力甚至派不上用场。但是设计模式不会,只要代码存在,不管是哪种语言,设计模式都可以指导你写出更好的代码。退一步来看,即使这项技能未被淘汰,但是随着一项新技能的生命周期从兴起走向高潮,再到饱和。除了对技能的要求会越来越高以外,付出与回报比也在逐步下降。以安卓为例,我是17年毕业的,按照校招惯例都是前一年招聘,所以招聘要求实际上是16年的市场要求,早在15年左右除了能独立开发常规的app外,我就已经掌握了动画,自定义View等那个时候属于高阶的知识,16年虽然不是移动互联网火爆的时候,但是那个时候做安卓开发找一份高薪工作相对还是比较容易的。但是现在来看自定义View,动画基本上已经是一个中级安卓开发就需要掌握的内容了,已经算不上高阶知识了。另外随着这几年人工智能等概念的火热,移动互联网已经趋于平淡,普通的安卓开发要找一份比较好的工作已经没那个时候容易了。这就是技能的一个很明显的特点容易过时,一旦这个技能趋于饱和或其生命周期走向衰退,也就意味着这项技能越来越不值钱了。但是任何一个技能领域都会存在一些高级技能,这个时候那些在这个领域已经成为资深或专家的开发者会成为最大的受益者。

那么是不是说技能就不重要呢?技能就不难呢?如果是为何公司招聘jd大部分要求的都是技能呢?这是因为虽然对于技能而言只要你肯花时间,学会它基本上是一件概率为100%的事情。但是做任何事情都包含了一个最基本的成本:时间成本。而对于公司而言产出一个东西都是有时间要求的,假设你目前不会安卓开发,虽然从理论上来说只要花时间你肯定能学会基本的安卓开发,比如3个月,但是公司很可能是需要在这个月就上线一个App。那么这个时候已经会这个技能就很重要了。如果完成一个任务,领导允许你一拖再拖那只能说你太幸运了。另一个方面很多高级技能不是孤立的,是依赖其他很多细节的,因为这项技能可能涉及非常庞大的相关知识和子技能,而要想掌握所有的这些相关知识是需要付出大量时间才能习得的。一方面这种技能需要大量时间才能习得,另一方面公司要求实现某个功能是有排期要求的,这2者之间的冲突就导致这项技能从落地角度来看属于比较难的技能。比如插件化技术。如果你对安卓的framework层不够熟悉是很难开发一个插件化框架的。而安卓的framework层牵涉的东西实在是太多了,代码量太庞大了。没有至少2-3年的开发积累是很难抓住和插件化相关的核心理论且将其系统化体系化的,这种技能就属于高阶技能了,但本质上还是技能,花1年左右时间绝大部分人都是可以学会的。

另外技能和思想不是严格意义上的割裂,很多技能中往往蕴藏着思想,所以我强烈建议大家在学习一项技能的时候不要仅仅只是去掌握这个技能本身,最好能去体会下其设计思想。以谷歌官方的网络框架Volley为例,会使用Volley框架提供的API接口去完成日常开发中的网络操作需求,这些仅仅只是技能层面的,很容易过时,意义不是很大。比如很多公司安卓团队现在使用OkHttp而不是Volley,这个时候你会不会Volley关系不大(同样的类推,如果某天出现了一个比OkHttp更强大的网络库XXX,业界都开始用XXX做网络请求了,那么这个时候你会不会OkHttp其实关系也不是很大)。所以完全可以甚至更应该去学习下Volley的设计思想,比如编码设计思想(面向接口编程),缓存设计,请求线程和队列管理的设计,超时重试机制设计等等。

最后我想说的是设计模式一点都不简单,它是一种思想,只能靠你去悟,不用拘泥于设计模式书上讲的那些示例。到目前为止我的设计模式系列就讲解完了,在这期间我也看过设计模式的一些比较经典的书籍,也查阅了大量的开源项目代码,去寻找设计模式的应用场景。但是我依然不敢说我学会了设计模式,只敢说我熟悉设计模式,如果你对设计模式有更好的学习方法,欢迎和我讨论交流。