0.5.1 模式的结构
每个作者都必须选择表达模式的形式。一些人采用的表达方式基于模式的一些经典教材,如[Alexander et al.]、[Gang of Four]或[POSA]。另一些人用他们自己的方式。我在这个问题上也斟酌了很久。一方面我不想像GOF一样太精练,另一方面我还要引用他们的东西。这就形成了本书的模式结构。
第一部分是模式的名字。模式名非常重要,因为模式的目的之一就是为设计者交流提供一组词汇。因此,如果我告诉你Web服务器是用前端控制器和转换视图构建的,而你又了解这些模式,那么你对我的Web服务器的架构就会非常清楚了。
接下来的两部分是相关的:意图和概要。意图用一两句话总结模式;概要是模式的一种可视化表示,通常是(但不总是)一个UML图。这主要是想给模式一个简单的概括,以帮助记忆。如果你对该模式已经“心知肚明”,只是不知道它的名字,那么模式的意图和概要这两部分就能为你提供足够的信息。
接下来的部分描述了模式的动机。这可能不是该模式所能解决的唯一问题,但却是我认为最具代表性的问题。
“运行机制”部分描述了解决方案。在这一部分,我会讨论一些实现问题以及我遇到的变化情况。我会尽可能独立于平台来讨论——也有一个部分是针对平台来讨论的,如果不感兴趣可以跳过这部分。为了便于解释,我用了一些UML图来辅助说明。
“使用时机”部分描述了模式何时被使用。这部分讨论促使我选择该模式而不是其他模式的权衡考虑。本书中很多模式都可以相互替代,例如页面控制器和前端控制器就可以相互替代。很少有什么模式是非它不可的。因此,每当我选择了一种模式之后,我总是问自己“你什么时候能不用它?”这个问题也经常驱使我选择其他方案。
“进一步阅读”部分给出了与该模式相关的其他读物。它并不完善。我只选择我认为有助于理解模式的参考文献,所以我去掉了对本书内容没有价值的任何讨论,当然其中也可能会遗漏一些我不知道的模式。我也没有提到一些我认为可能读者无法找到的参考文献,再就是一些不太稳定的Web链接。
我喜欢为模式增加一个或几个例子。每个例子都非常简单,它们是用Java语言或C#语言编写的。我之所以选择这两种语言,是因为它们可能是目前绝大多数专业程序员都能懂的语言。必须注意,例子本身并不是模式。当你使用模式时,不要想当然地认为它会和例子一样,也不要把例子看成某种形式的宏替换。我把例子编得尽量简单以突出其中模式相关的部分。当然,省略的部分并不是不重要,只是它们一般都特定于具体环境,这也是为什么模式在使用时一般都必须做适当调整。
为了尽量使例子简单但是又能够突出核心意思,我主要选择那些简单而又明确的例子,而不是那些来自于生产系统中的复杂例子。当然,在简单和过分简单之间掌握平衡是不容易的,但是我们必须记住:过分强调具体应用环境反而会增加模式的复杂性,使得模式的核心内容不易理解。
这就是为什么我在选择例子时选取的是一些相互独立的例子而不是相互关联的例子。独立的例子有助于对模式的理解,但是在如何将这些模式联合在一起使用上却支持不多。相互关联的例子则相反,它体现了模式间是如何相互作用的,但是对其中每个模式的理解却依赖于对其他所有模式的理解。理论上,是可以构造出既相互关联又相互独立的例子,但这是一项非常艰巨的工作——至少对于我来说是这样。因此,我选择了相互独立的例子。
例子中的代码本身也主要用来增强对思想的理解。因此,在其他一些方面考虑得可能不够——特别是错误处理,在这方面,我没有花费很多笔墨,因为到目前为止,我还没有得出错误处理方面的模式。在此,那些代码纯粹用来说明模式,而并不是用来显示如何对任何特定的业务问题进行建模。
正是基于这些原因,我没有把这些代码放到我的网站上供大家下载。为了让那些基本的思想在应用设置下有所意义,本书的每个示例代码都充满着太多的“脚手架”来简化它们。
并不是每个模式中都包含上面所述的各个部分。如果我不能想出很好的例子或动机等内容,我就会把相应部分省略。