关于一等抽象数据类型的思考
在本节课中,我们将简要讲解首类ADT模式。
对设计模式的批评
一种对《设计模式》常见的批评是,这些模式仅适用于像 C++ 或 Java 这类支持消息传递的面向对象语言。许多人认为,设计模式实际上是对语言功能缺失的一种变通方案。这种观点背后的逻辑是:需要使用设计模式,正说明某种编程语言在表达能力上有所不足。
这种说法确实有一定道理。《设计模式》一书本身也明确指出:
“编程语言的选择至关重要,因为它会影响人们的思维方式。”([Gamma 等人])
书中进一步说明,其模式目录基于的是“Smalltalk / C++ 层级的语言特性”。如果我们采用比 C++ 更高级的语言,例如 Common Lisp,就会发现许多设计模式不再适用,原因如下:
- Common Lisp 拥有完全不同的设计空间。
- 许多模式已被内化到语言本身之中。例如,策略模式(Strategy)已体现在头等函数中,而访问者模式(Visitor)则通过 Common Lisp 对象系统中的泛型函数模型得以内置支持。
但语言的“强大”始终依赖于具体上下文。在某些问题场景下,即使 Common Lisp 功能强大,也不一定是最合适的选择;同样地,C 语言也未必在所有情况下都是最佳选项。原因可能包括:
- 技术层面
- 战略层面
- 社会因素
- 文化因素
对我们而言,更有意义的是从 C 语言的视角来审视设计模式。《设计模式》提到,在过程式语言中,通常也会出现诸如封装这类模式。一等抽象数据类型(First-Class ADT)就是这样一个例子。
封装
封装是一种管理复杂性的工具,用于分离问题的不同方面。通过封装,我们实际上可以获得设计的两个视角:
- 外部行为
- 内部细节
根据所扮演的角色不同,我们可以选择从其中任一角度来观察设计。在一个成功的设计中,这两个视角应当是正交的,可以独立变化。
和其他任何模式一样,封装也应审慎使用,需把握分寸与恰当性。我们并不会将所有模块都设计成一等抽象数据类型。相反,该模式通常在构建应用程序不同层次之间的边界时才显得尤为有用。一等抽象数据类型可作为不同开发团队之间的技术防火墙,使一方能够发布接口的同时隐藏实现细节。这样的设计有助于多个相关但不同的部分并行开发。