我们编写软件是为了解决问题。自从第一台可编程计算机能够解决之前难以解决的问题(例如计算π的第400 052 412 247位数)之后,程序员编写了无数的程序来解决大量的问题。他们花费大量时间快乐地编写代码来解决手的问题,同时其他人为同类的或者相似的问题编写解决方案。为什么程序员倾向于创造解决方案而不是寻找一个已经存在的解决方案,这是有很多原因的。一个原因,是我们通常会相信我们当然能够得到一个更好的解。对于我们其中很多人来说,编程就像棋类运动对于棋类狂热者一样充满着乐趣。当考虑为什么程序员不断地编写同样的解决方案时,还有一些更重要的原因:
·程序员不会意识到问题已经被解决。当我们讨论问题领域时,我们将会看得更远。
·虽然程序员知道问题已经用相似的方法解决了,但是现存的代码是否适合程序员面对的问题事实上并不清楚。
·并不容易找到完全或者能够经过小小修改适合手头问题的代码。
模式:一种交流语言
在20世纪80年代末,一小部分充满想象力的软件开发者开始寻找新的办法,使得彼此能够顺利交流软件设计经验。其中一些工作恰好是由Christopher Alexander负责,他是伯克利加利福尼亚大学建筑系的一位教授。他在1977年编写了《A Pattern Language:Towns,Buildings,Construction》一书。在这个有发展潜力的工作中,Alexander开发了一套用于描述建筑结构设计的理论。1987年,Kent Beck和Ward Cunningham,这两位面向对象范型的著名领导者,在当年的面向对象编程系统、语言和应用大会(OOPSLA)上介绍了如何将设计模式应用到编程。这个想法迅速流行开来,人们开始思考有关软件设计模式方面的东西。在1995年,Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides四个人(GoF)编写了一本具有开创意义的书——《Design Patterns:Elementsof Reusable Object-Oriented Software》(Gamma等人,1995),关于设计模式的研究和应用活动迅速开展起来。
和其他的优秀思想一样,大量的模式被迅速应用到软件工业,使用模式来设计软件已经成为很普遍的事情,甚至到了什么东西都可以用模式来描述的地步。编码规范是一种模式,和同伴坐在一起调试程序也是一种模式。模式是精确和简洁交流良构概念的最好方法。我们将模式应用到计算机科学其他领域,例如使用模式来描述本书的算法。
在描述我们如何为本书的算法构造模式语言之前,先看看什么是模式,为什么它是如此优秀。关于什么是设计模式,我们推荐如下定义:
设计模式是一个验证过的解决方案,这个解决方案能够解决一般问题。
这个定义非常简短,但是表达出了设计模式的本质。首先,设计模式是对实际问题的解决方案。事实上,它是对一个普遍问题集合的通解。但是,设计模式不是模板,只做简单地填空是行不通的。它是一种方法,或者是一个计划,用来解决一个特定类型的问题。在你的工具箱里装上一系列的设计模式,你就踏上了软件设计大师之路。
我们能够从不同的角度考虑算法。很多开发者喜欢在书中或者在一些网站上找到算法,复制代码,然后运行,或者可能还需要一些测试,然后迅速地转移到下一个任务中。我们认为,这种行为对于提高自身对于算法的理解一点用处也没有。事实上,这种行为将会使得你在选择算法实现的时候处于一个错误的位置。记住第1章Graham是如何盲目地选择了二叉树却没有不厌其烦地去平衡它。当你使用了看似能解决问题的最初的想法,那么接下来会发生什么就可想而知了。
所以,问题是你如何快速定位到正确的算法并且对它有足够的了解,确保你已经做出了正确的选择。模式能够帮助我们这样做。事实上,算法就是对于已知问题的验证过的解决方案,这也符合我们对于设计模式的定义。
算法模式的格式
设计模式通常表示为一种模式化的方法,使得开发者能够易于交流。并不是所有的模式作者或者书籍都赞成使用特定的格式,但是它们有很多东西是相同的。我们采用了类似于模式的方法来阐述算法,因为我们相信这样做,读者能够更高效地阅读。如果你能够对本书内容有更好的理解,可以将这种模式化的方法纳为己用。
按照我们的模式语言,每个算法用一些固定的章节来表述。有时如果一个章节被认为是对描述算法没有帮助的话,那么这个章节可以省略掉。有时我们可能需要增加一些额外的章节来描述一些特定的知识点。