
1.1 设计模式的历史
设计模式对开发人员来说并不是一个新的概念。在个人计算机变得便宜和流行的20世纪80年代,编程这个职业兴起后,开发人员为不同的应用程序编写了大量的代码。
记得在我14岁那年,学习BASIC程序的GOTO语句是一件超酷的事情。它能够让我在任何时候控制程序执行到其他的代码块中。也许这并不奇怪,当我在大学学习结构化编程和Pascal语言时,我开始意识到GOTO语句是如何产生混乱无序的意大利面条式代码的。使用GOTO进行分支是一种模式。它不是一个好的模式,因为它让代码变得很难理解、跟踪和调试。它按现在通俗的说法叫作反模式。当涉及结构化编程技术时,以小的函数组织代码也是一种模式,这种模式已被视为编程课程中的主流学科。
当我大学毕业时,我开始了我的编程生涯,并花费了大量时间进行“黑客入侵”。我有机会进行各种研究,并了解系统的设计方式。比如,我了解到UNIX操作系统的设计非常漂亮。那是因为它包含了许多小的程序,每个小的程序并没有大量的函数,但是你可以用多种不同的方式组合这些程序,让它们去解决更加复杂的问题。我也喜欢出自麻省理工学院人工智能实验室的Scheme编程语言。这种语言的简洁和函数多样性一直令我惊叹。Scheme的发展可以追溯到Lisp语言,而Lisp对Julia的设计也有一定的影响。
1.1.1 设计模式的兴起
1994年,在我沉浸于C++和金融应用的分布式计算时,4位软件专家,也就是著名的四人组(Gang of Four,GoF),走到一起并出版了一本设计模式的书,这本书如暴风雨般地在面向对象编程社区流行。他们收集并分类了开发大型系统时通常使用的23种设计模式,还选择使用统一建模语言(UML)以及C++和Smalltalk解释概念。
这是设计模式第一次被收集、组织和解释,并广泛传授给软件开发人员。将这些模式组织在高度结构化且易于使用的格式中也许是GoF最重要的决定之一。从那时起,开发人员之间就能够轻松地交流如何设计软件了,而且他们可以通过通用符号直观地展示软件的设计。当一个人谈论Singleton模式时,另一个人可以立即理解甚至在他的脑海中想象组件工作。这样不是非常方便吗?
更令人惊讶的是,当谈到构建好的软件时,设计模式突然变成了福音。有些情况下,设计模式甚至被认为是编写优秀软件的唯一方法。GoF模式在整个开发社区中广为传播,以至于许多人到处使用,且无故滥用。就像当你拿着一把锤子时,一切看起来都像钉子!并不是所有问题都可以用相同的模式解决,也并不是所有的问题都应该用相同的模式解决。当设计模式被过度使用或滥用时,代码将变得更加抽象、更加复杂且难以管理。
那么,我们从过去的经历中学到了什么呢?我们认识到,每一种抽象都是有代价的。每个设计模式都有其自身的优缺点。本书的主要目的之一是不仅讨论如何使用,还要讨论为什么用、为什么不用,以及在什么情况下应该使用或不应该使用模式。作为软件专业人员,我们用这些信息武装自己的头脑,能够对何时应用这些模式做出正确的判断。
1.1.2 关于GoF模式的更多思考
GoF模式主要分为3类:
·创建型模式:这种模式包含如何以各种方式构造对象。由于面向对象的编程将数据和行为组合在一起,并且一个类可以继承祖先类的结构和行为,因此在构建大型应用程序时会涉及一些复杂性。创建型模式有助于在各种情况下标准化对象创建方法。
·结构型模式:这种模式包含对象如何扩展或组成更大的对象。它的目的是允许软件组件更容易重用或替换。
·行为型模式:这种模式包含如何设计出用来执行不同任务并相互通信的对象。大型应用程序可以分解为独立的组件,并且代码变得更易于维护。面向对象的编程范式要求对象之间进行密切的交互。这些模式的目的是使软件组件更灵活,更便于彼此协作。
其中一种思想流派认为创建设计模式是为了解决其各自编程语言中的限制。GoF的书出版两年后,Peter Norvig研究发现23种设计模式中的16种不是必需的,或者可以使用诸如Lisp之类的动态编程语言进行简化。这是一个非常重要的发现。在面向对象程序设计的上下文中,从类层次结构进行的其他抽象要求软件设计人员考虑如何实例化对象以及如何彼此交互。在强类型的静态类型语言(比如Java)中,甚至有必要对对象的行为和交互进行推敲。在本书第11章中,我们将回到这个主题,并讨论与面向对象编程相比,Julia工作方式的不同之处。
现在我们将从基础知识入手,并回顾一些软件设计原则。这些原则就像北极星一样指导我们构建应用程序。
1.1.3 在本书中我们如何描述设计模式
如果你不熟悉Julia编程,那么本书将帮助你了解如何编写更加通用的Julia代码。我们还将重点介绍现有开放源Julia生态系统中已经使用的一些最有用的模式。其中包括Julia自己的Base和stdlib包,因为Julia运行时很大程度上是用Julia本身编写的。我们还将引用其他用于数值计算和Web编程的包。
为了便于参考,我们按名称组织模式。例如,“Holy Traits”模式是指实现特质的特定方法。领域特定语言模式讨论如何构建新语法来表示特定领域概念。名称的唯一目的只是为了便于参考。
当我们在本书中讨论这些设计模式时,我们将尝试了解它们背后的动机。我们要解决什么具体问题?设计模式能发挥作用的现实情况是什么?然后,我们将详细介绍如何解决这些问题。有时,可能有几种方法可以解决相同的问题,在这种情况下,我们将研究每种可能的解决方案并讨论其优缺点。
话虽如此,对我们而言重要的是要了解使用设计模式的最终目标是什么。为什么我们首先要想到使用设计模式?要回答这个问题,首先了解一些关键的软件设计原则会很有用。