Bruce Eckel
读完需要
4
分钟速读仅需 2 分钟
布鲁斯 • 埃克尔(Bruce Eckel),C++ 标准委员会的创始成员之一,知名技术顾问,专注于编程语言和软件系统设计方面的研究,常活跃于世界各大顶级技术研讨会。
他自 1986 年以来,累计出版 Thinking in C++、Thinking in Java、On Java 等十余部经典计算机著作,曾多次荣获 Jolt 最佳图书奖(被誉为“软件业界的奥斯卡”),其代表作 Thinking in Java 被译为中文、日文、俄文、意大利文、波兰文、韩文等十几种语言,在世界范围内产生了广泛影响。
面向对象设计模式的演变历史参见《设计模式:可复用面向对象软件的基础》(以下简称《设计模式》)中的相关记载。
《设计模式》这本书中演示了 23 种针对特定问题类型的不同解决方案。本章将通过各种示例来讲解设计模式的基本概念。这会激发你阅读《设计模式》的兴趣,这本书已经成为面向对象程序员的宝典之一。
本章最后引入了一个关于设计演进过程的例子,模拟了垃圾分类场景,从最开始的设计开始,逐步改进逻辑和流程,最终演进到更好的设计。可以将该演进过程看作某种演进原型——将满足某个特定问题的方案发展为可满足一类问题的灵活方案。
1
设计模式的概念
一开始,你可以将模式视为一种解决特定类型问题的兼具巧妙和洞察力的方法。模式看起来就像很多人已经解决了问题的所有细节部分,然后想出了最通用和灵活的方案。你可能以前遇到过这个问题,并且解决了,但你的方案很可能并不如模式中的那么完善。
它们虽然被称为“设计模式”,但实际上与设计领域并无关联。模式似乎和传统的分析、设计和实现的思维方式不同。模式在程序中体现了完整的思想,因此它有时会出现在分析或高层设计的阶段。由于模式在代码中有着直接的实现,你可能并不希望它出现在低层设计或实现阶段,甚至是维护阶段之前。通常,在进入这些阶段之前,你不会意识到你需要一个特定的模式。
模式的基本概念也可以看作程序设计的基本概念:增加一层抽象。无论何时,如果你要抽象某个事物,实际上就是在隔离某个特定的细节,而最有说服力的背后动机之一就是:
将会变化的事物和不会变化的事物分开。
还有一种说法,一旦你发现程序的某个部分可能会由于某种原因而发生变化,抽象就可以防止这些变化引发整个代码中的其他变化。
通常,要实现优雅且易维护的设计,其中最困难的部分是如何发现我所说的变化的向量(the vector of change,“向量”指的是最大的变化率,而不是某个集合类 )。这意味着要找到系统中最重要的会变化的事物。换言之,是要找到最大的(改动)成本。一旦找到了变化的向量,你就掌握了构建设计的关键点。
因此设计模式的目标就是隔离代码中的变化。如果能从这个角度看待设计模式,那就应该能意识到本书中已经出现过很多设计模式了。举例来说,继承可以看成一种设计模式(尽管是由编译器实现的)。它使你可以在具有相同接口的对象(保持不变的事物)中表现出行为的差异(变化的事物)。组合也可以被认为是一种模式,因为它使你可以动态或静态地改变实现类的对象,并由此改变对象的行为方式。
你也已经看到了另一种出现在《设计模式》中的模式:迭代器(Java1.0 和 1.1 任性地称其为“枚举”,Java 2 集合则称其为“迭代器”)。这会在遍历并逐个选择元素时隐藏集合的特定实现。迭代器使你可以在无须关心某个序列的构造方式的情况下,实现对该序列所有元素的某种操作。由此你的代码可以用于任何实现了迭代器的集合。
虽然设计模式很有用,但有些人断言:
设计模式代表着语言的失败之处。
这个看法很重要。比如说,某模式只是在 C++中很合理,但在 Java 或其他语言中却可能并无必要存在。出于这个原因,不能只是因为一个模式出现在了《设计模式》中,就认为它在你的语言中很有用。