Web标准化交流会归来:分享一些自己深入理解的“设计模式”

本文摘自 勾三股四 更早时期的 不老歌 博客。


上个月的Web标准化交流会中,看到了有关“Javascript”设计模式的探讨。交流会的探讨虽然结束了,但还是有点意犹未尽的感觉。

“设计模式”这个词最早就是从Java那里听来的,相信很多工程师的私人书架上都有这本书。由于交流会话题的关系,突然对这本书颇有兴趣。所以连夜把Java设计模式一书温习了一番。

看过之后,再次证明了一点:一本好书,每次读它,都会有新的收获。

这次再看这本书的时候,脑袋里已经不再是那些Java代码和UML框线图了,而更多的是Javascript、Ajax角度的思考,从而归纳出语言无关、面向对象无关的抽象理解。这应该才是真正的“模式”吧。

所以我突然觉得,“模式”这种东西,是一种极其确定的,高度一致的,可以保证解决确定问题的流程和思维,不是能够通过一门语言或一个实例甚至几行代码就能够阐述的。而且“模式”与“模式”之间并不是并行的,它们在横向分类或纵向过程中产生联系,形成了丰富而又清晰的方案。我们如果对其进行合理的识别和运用,就可以通过有限个“模式”解决开发中大部分的问题。

-------------------------------------------

首先,“迭代器”就是个最简单也是最常用的“模式”,也就是说我们需要对一个集合中的每一个元素进行相同的操作。像:

for (var i in obj) { var member = obj[i]; ... }
for (var i = 0; i < arr.length; i++) { var item = arr[i]; ... }

都是迭代器模式,如果遇到其它的数据结构(比如dom链式表),就需要不同的方法,但模式是不会变的:

var node = root.firstChild; while (node) { ... node = node.nextSibling;}

它们有共同的“模式”,就是我们需要一个角色,通过一个确定的规则,逐个访问到集合中的元素,最后结束,期间要保证不能重复访问元素

以上就是“迭代器”模式的含义。今后遇到类似的技术需求,就可以大胆、机械的直接运用“迭代器”模式了,不用费时费力胡思乱想了——这是模式希望带给我们的。

-------------------------------------------

“模板方法”模式提醒我们的是,遇到数据相同,表现不同的东西,可以创建不同的表现“模板”,让数据和表现分离的同时,方便数据丢到不同的“模板”中,快速展现出不同的视觉效果。比如WordPress博客站令郎满目,但其实数据库结构和业务逻辑都是一样的,不一样的地方,就是“模板”了。以后想自己建个博客,不用多想了,搞来个WordPress或Typecho换换模板就行了。WordPress专门把和“原材料”无关的界面表现独立开来,正是运用了这种“模板方法”模式。

-------------------------------------------

“工厂方法”模式是“模板”模式的一个典型应用——这里可以看出“模板”之间的关系可能是各种各样的,这里他们两个就是包含关系。有的时候加工出一种对象比修改、使用、删除它要复杂的多,性质也相对独立,就可以把这类任务交给这个类的一个特别设计的类或函数。正如“工厂”的字面意思所言,把外部依赖性不强却又复杂的工作拿给“工厂”里,狭义意义里的程序都是不知疲倦的,所以这个工厂比现实中的血汗工厂还要无情而又保证产出质量。是每一个准求利益的人的福音。

-------------------------------------------

有的时候我们会单纯的认为,只有抽象出来的东西,才可以做各种各样的事情。真实存在的东西,都只能完成特定的任务。其实并非那么绝对,首先“单例”模式告诉我们,抽象出来的东西也可以只用来完成特定的任务;而“原型”模式、“生成器”模式则告诉我们,具体的实例也有能力生产出更丰富的内容,完成丰富的任务。

-------------------------------------------

设计模式还告诉我们,程序的世界里,“分久必合、合久必分”。

“组成”模式和“装饰者”模式,分别阐述的思想是:将内容和容器的形式统一起来,最易懂的例子就是文件和文件夹组成的文件系统了,文件可以放入文件夹,但文件夹本身和文件一样都是文件系统的最小单位;对数据内容的创建和包装都看作是生成新内容,从这个角度讲,对数据的创建和修改可以统一。此所谓“分久必合”。

“访问者”模式和“职责链”模式,则是从另外一些角度,帮助程序员将大问题分离开来:“访问者”是提供“到此一游”的方法,将数据本身和数据操作分离;“职责链”则是把状态本身和状态操作分离。此也所谓“分久必合”。

“桥接”模式和“策略”模式,从名字听起来很空,实际想表达的意思就是:先把综合问题区分为几个独立问题,然后把各自解决的结论组合起来;或者根据上下文不同,选择不同的处理策略,走不一样的发展道路。此所谓“合久必分”。

-------------------------------------------

“享元”模式是另外一个我认为需要强调的设计模式,它的思想是尽可能的把程序结构分得很细,并将常用的东西作为程序的元来供大家重用。我们在编写各种底层js框架的时候,就需要大量这方面的思考。但即使不是底层的实现,我们在设计上层建筑的时候同样要时刻注意,是否可以把某些程序段变成“元”,并补充到类库或框架或全局变量中以供大家重用。

-------------------------------------------

最后介绍两个更为抽象的模式:“命令”模式和“解释器”模式。“命令”模式旨在把任何层面的程序或操作规约,并转换为统一格式的行为表述——我们的各种log日志就是在做这件事情;而“解释器”则旨在创建一种语法规则,通过这个规则,对相同数据类型的不同数据实体解读出不同含义的内容,各种协议(比如HTTP协议、FTP协议)就是在做这件事情。

-------------------------------------------

至此,还有若干个设计模式没有提及,不过上述内容基本覆盖了70%我们在程序设计和编写中需要考虑的各种问题了。这些模式是从思路层面为大家提供一种“最佳实践”,让我们更高效准确的完成程序的设计或算法的设计。同时也指导我们创造出更多的“模式”和“最佳实践”。如果诸位通过上述讲解有所领悟,那将是我莫大的荣幸。

以上