陈梓涵:我们为什么要学习设计模式

先说点题外话。最近想做一个Computational Graph Database (https://github.com/vczh/vczh_toys/blob/master/PlayWithLinux/Database/draft),顺便练习一下Linux下写C++程序的技巧,深刻的体会到了一个道理。Linux下有这么多烂工具,每个人做了一个工具,都会有另外一个人觉得这个工具很烂,然后就做了一个更烂的来恶心他。我本着这种开源的精神,写了一个GayMake(误,于是就有了这次的贴图。倘若最后这个项目没有坑,以后开源狗跟我吵架,我就可以糊他一脸,说【在linux瞎搞编程你也搞不过我】,啊哈哈哈哈。

不管是设计模式也好,别的模式也要,他都是为了解决问题而发明的有效的方法。除了我们已经熟悉的23种设计模式以外,还有MVVMCombinator等其它的东西,都已经是前辈们经过多年的摸爬滚打总结出来的,其有效性不容置疑。我这篇文章也不会用来证明设计模式是有用的,因为在我看来,这就跟1+1=2一样明显(在黑板上写下1+1=2)。

架构的设计也是一样。你要做一个分布式系统,在哪里放gate way,在哪里放database,在哪里放cache,在哪里放计算节点,这些东西都已经是早就总结好的了。类似的东西就叫pattern。一个architecture就是由很多个pattern组合起来的。除此之外,做游戏也好,做编译器也好,设计数据库也好,每一大类的问题都有他们自己的pattern。他们的档次跟设计模式不一样,但是要解决的问题都是一样的,就是让你高效地解决问题。

那为什么我们需要学习设计模式呢?这很明显,这就跟我们看别人的代码来学习一样,是为了学习里面的精髓。每一本设计模式的书都会告诉你,这些都是在讲究如何对修改封闭,对扩展开放的事情。前几天我在看几年前一个数学老师的公开课,叫数学大观(数学大观 - 专辑)。我觉得里面有句话就讲得很好。我们学东西,重要的是学idea,次要的是学technique。翻译成编程的语言就是,我们学设计模式,是为了学习如何合理的组织我们的代码,如何解耦,如何真正的达到对修改封闭对扩展开放的效果,而不是去背诵那些类的继承模式,然后自己记不住,回过头来就骂设计模式把你的代码搞复杂了,要反设计模式。不要见什么都反,有空应该好好读一读毛*东的辩证法,知道设计模式有好的一面也有不好的一面,当然总的来说设计模式好的一面比较大。

设计模式要是真的学会了,你们会发现在写代码的时候,脑子里根本没有什么设计模式,你都已经融会贯通了。代码写完了一看,这里有模式,那里也有模式。这就如同我们讲话不会去考虑语法,但是说出来大部分的话都是符合语法要求的。这也如同我们写程序的时候不会总是去想程序的语法的问题,我们自然而然写出来的东西就是可以编译的。道理都是一样的。

不过为了合理的利用设计模式,我们应该明白一个概念,叫做扩展点。扩展点不是天生就有的,而是设计出来的。我们设计一个软件的架构的时候,我们也要同时设计一下哪些地方以后可以改,哪些地方以后不能改。倘若你的设计不能满足现实世界的需要,那你就要重构,把有用的扩展点加进去,把没用的扩展点去除掉。这跟你用不用设计模式没关系,跟你对具体的行业的理解有关系。

倘若你设计好了每一个扩展点的位置,那你就可以在每一个扩展点上应用设计模式,你就不需要去想到底这个扩展点要怎么实现他才会真正成为一个扩展点,你只需要按照套路写出来就好了。

如果你发现你最后的代码长得跟设计模式不一样,这不一定代表你没有用到设计模式,也不一定代表这个设计模式没有用。设计模式归根结底就是因为你使用的程序语言的抽象能力不足才发明出来的。譬如说那个Listener模式,在C#里面就是一个event关键字搞定,你不需要去写一大堆框架代码来增加这个扩展点。相反,你在Java里面就需要这么做。因此你可能觉得Listener模式在Java有用,在C#没用,其实不是这样的。

真正的情况是Anders Hejlsberg很牛逼,他帮你把这个设计模式做进了语法,你不需要痛苦地写一大堆框架代码就可以用了。这种东西就叫语法糖。有语法糖就不需要写框架代码抄设计模式,没有语法糖你就需要写框架代码抄设计模式。为了解决这一个问题,你所需要放进去的扩展点,无论你用什么语言,他都是这么多。区别只有你到底是怎么写出来的。所以语法糖好不好,当然好。你不想学语法糖就老老实实抄设计模式,人家也没有把语言设计成你学不会语法糖就不能用。这很公平。

我为什么喜欢Haskell、C++、F#这样的语言,因为它们的代码是可以被计算出来的,因此我可以根据需要随时添加我自己的语法糖,而且还不需要改变语言的语法。当然根据这条标准,我本应该喜欢Lisp的,无奈Lisp的括号太多,噪音太大,我不喜欢这样的东西。同样的理由也见GayMake。那么简单的东西要生成一大坨参杂了各种符号的字符的makefile,那个makefile根本看不懂,虽然已经很接近我手写出来的样子了。其实我就是看了一遍makefile的说明,然后手写了几个makefile,然后照着我写出来的makefile把makefile生成器给写出来的。

设计模式的好处还有一点,就是他做出来的样子性能很高。虽然扩展点的意思就是我在编译的时候不知道到底会命中哪个扩展,但是大多数扩展都是O(1)命中的(除了责任链模式) 。与之相关的还有IoC,也就是Inverse of Control,这也是一个好东西。Inverse of Control讲的是,类与类之间的依赖是可扩展的,而且是强类型的,并且你还不需要在类的内部指定(因此跟组合不一样)。当一个类需要用到他的依赖的时候,他不需要主动去获取他,而是可以等别人把依赖塞给他,然后再做事情。类似的事情在GacUI(www.gaclib.net)里面大量的使用。

讲了这么多好处,那到底我们要怎样才能学会设计模式呢?答案只有一个,就是创造条件去使用设计模式。很多人总是觉得,要通过简单的程序和例子来学设计模式。这是不对的。设计模式就是因为情况复杂了所以才会出现的,所以我们只能通过复杂的程序来学习设计模式。你不管看别人的程序也好,自己写程序练习也好,那必须要复杂,复杂到你不用设计模式就做不下去,这才能起到学习设计模式的作用。

为什么我对设计模式那么熟悉,这跟我长期以来造的轮子都很复杂是有关系的。不过我有很多设计模式的知识和体会是在搞各种各样的奇怪的语言,譬如说Haskell啊Prolog这些东西才学到的。为什么呢?有些模式就是从那个语言出来的。你倘若不去搞一搞那个语言,你就不会去看到那个语言的材料,你就不知道那个模式可以被用到你自己喜欢的语言上面。你可能会想,那总有人会这么做啊,譬如说我是吧。但是我是不会把应用到正常语言的过程详细的搞出来给你们听的。原因在于,那个模式,譬如说Combinator,在Haskell下面搞出来很容易,但是在C++里面搞出来就会有大量的框架代码。所以你去看Haskell如何用Combinator,肯定比看C++如何用Combinator难度要低得多。所以倘若你们问我怎么搞定Combinator,我只会告诉你,好好弄Haskell,然后去看Combinator。因为用C++解释太麻烦了,我不会这么做的。

当然,你们有些人肯定不会因为这样就去看Haskell,这只能说明学习Combinator对你来说不是一个迫切的事情。你没了Combinator还能活下去,只是你永远也体会不到你的程序用Combinator可以简化的同时还容易扩展到什么程度。

最后讲一点,Dog fooding是很重要的。微软的东西为什么这么复杂还能继续开发下去,除了代码组织得好以外,质量也好。这跟我们长期自己使用自己的软件给他们积极地爆bug是有关系的。你们自己学东西也一样。譬如说你学了如何自己实现正则表达式,你就把它实现出来,然后以后就用自己的这个实现来干活。东西用的多,爆出来的bug也就多,你对他的理解也就越深刻 。倘若你们只是看一眼文章,自己做个小玩具,甚至连小玩具都不做,就这么过去了,肯定什么也学不会。

时间: 2024-11-05 11:39:46

陈梓涵:我们为什么要学习设计模式的相关文章

设计模式——为什么要学习设计模式

不好程序: 1 情况之一:重复的代码多到一定程度,维护的时候,可能就是一场灾难. 好程序的标准(灵活性好): 1 容易维护,容易扩展,容易复用: 2 编程有一定的原则,就是用尽可能的办法去避免重复: 面向对象的好处:通过封装,继承,多态把程序的耦合度降低,用设计模式使得程序更加的灵活,容易修改,并且易于复用: 聚合(Aggregation):表示一种弱的“拥有”关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分. (用空心的菱形+实线箭头表示) 合成(Composition):是一种

Net设计模式实例系列文章总结

1 什么是设计模式 设计模式是对在软件设计过程中重复出现的问题提出了一种比较好的解决方案.正如一位专家所说:设计模式是对程序设计人员经常遇到的设计问题的可再现的解决方案(The Smalltalk Companion).GOF设计模式通常被认为是其他设计模式的基础,随着业务复杂度的增大,会不断涌现新的设计模式,而这些新的设计模式一般会以GOF模式理论为参照. 2 为什么要学习设计模式 从个人职业规划来考虑.一位软件开发工程师随着编码量的增加,开发经验的增加,软件理论理解的加深,会不由自主地想一些

设计模式初探—简单工厂模式

为什么要学习设计模式? 可重用.可维护.可扩展.灵活性好 什么是简单工厂模式? 从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一.简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例.简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现. 简单工厂模式的好处? (1)将具体业务和实现进行分离 (2)将多个具体业务之间进行解耦 解决的问题? 单独的类来创造

常用JavaScript设计模式

前言 为什么要学习设计模式? 解耦合.解决复用.提高观察高度 创建型模式 结构型模式 行为型模式 设计原则

设计模式(二) 模式语录

设计模式--模式语录 <Design Patterns:Elements of Reusable Object-Oriented Software>尽管是英文描述的,了解和喜欢设计模式的同仁看到这个书目,熟悉得犹如看到下面这张图: 当你发现这不是一张完整的图的时候,不要以为被我忽悠了,即便你是被我善意地小小忽悠了一下,但你忽悠不了你自己(GOF的设计模式),很快其他部分自然而然的在你脑海里呈现出来.如果说你还没有打算现在或者将来去学习和使用设计模式来改善自己的编码和设计,请你不要觉得我在故弄玄

设计模式详解(总纲)

转载:http://www.cnblogs.com/zuoxiaolong/p/pattern1.html <简介> 说到设计模式,当初第一次听到时,第一反应就是很深奥,完全理解不了这个概念到底是什么意思,下面我先从网上摘录一份定义. 设计模式(Designpattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结. 上面是百度当中的解释,来解释一下这句简单的话的含义,几个关键词.  反复使用:这个不用过多解释,设计模式被使用太多了,上个系列spring源码当中就出现了

一步步学习设计模式系列之你必须要了解的概念和UML工具(一)

一.为什么要学习设计模式 使用设计模式的根本原因是为了保持类之间的隔离,防止相互之间了解太多内容:另一个重要的原因是,使用设计模式可以帮助我们避免重复开发.有很多策略能让程序员达到分离类的目的,其中包括封装和继承.一个继承父类的类能访问父类中所有非私有的的东西,如果以一个功能完整的类来继承层次结构,可能会过多的限制自己,也会给特定方法的实现带来累赘.因此设计模式建议应遵循以下原则:面向接口编程,而不是针对实现编程:优先使用对象组合,而不是继承. (1)面向接口编程,而不是针对实现编程概述: 就是

Android 4.4(KitKat)中的设计模式-Graphics子系统

本文主要从设计模式角度简单地侃下Android4.4(KitKat)的Graphics子系统.可以看到在KitKat中Google对code还是整理过的,比如替换了像SurfaceTexture这种第一眼看到不知所云的东西,去掉了像ISurface这种打酱油的定义,改掉了明明是SurfaceHolder类型却死皮白脸叫surface的变量.自从修正了这些晦涩逆天的概念后,妈妈再也不用担心我看不懂Android的code了.当然仍然有不少legacy code,如果没看过以前版本的话会有些小迷茫,

《HeadFirst设计模式》读后感——对学习设计模式的一些想法

最近看完了<HeadFirst设计模式>,GOF的<设计模式——可复用面向对象软件的基础>的创建型模式也读完了,经历了从一无所知到茅塞顿开再到充满迷惑的过程. 不得不说<HeadFirst设计模式>是一本非常好的入门书,每一章都是先提出问题,然后讨论.分析,引导出相应的设计模式,再一步一步的实现,幽默的语言和有趣的插图,让人轻松愉快的学习了一个模式.之前我对学习设计模式是有很大的畏难情绪的,上网一搜一看,妈个鸡,动不动就什么GOF什么23个设计模式,然后找个工厂方法或者