设计模式的识别:经验丰富的开发者经常会发现,新问题往往与他们之前所遇到的问题存在相似之处,虽然这些问题和解决方案可能各不相同。正是这些问题之间的共性催生了设计模式的概念:将对类似问题解决方案的理解泛化和形式化。
模式孵化与挖掘:
- 模式孵化:模式孵化涉及识别问题的本质并在模式库中寻找最佳匹配的解决方案。这一过程不是去创造新的设计模式,而是在已有的设计模式库的基础上进行开发,旨在构建适应特定应用场景的有效方案。
- 模式挖掘:模式挖掘是一种识别和记录新模式的过程,包括将问题本质化,创建一个通用解决方案,并理解该解决方案在具体应用场景中的影响和后果。
设计模式的本质:设计模式不仅仅关于软件的重用,它更代表了概念的重用。设计模式提供了一种通用的指导,帮助开发者在特定情况下优化分析模型,包括特定的优化策略和预期效果。
优化的权衡:优化往往涉及在提升系统某些方面性能的同时,牺牲其他方面。例如,一些设计模式可能提高代码的可重用性,但以牺牲最差性能为代价。优化是一个涉及多方面考量的权衡过程,需要在不同的系统属性间进行细致的平衡和抉择。
3.3.1 何为设计模式
设计模式定义:
- 通用解决方案:设计模式是对常见问题的通用解决方案,这些问题足够频繁,以至于有必要创建一个普遍适用的模板。
- 广泛适用性:设计模式具有广泛的适用性,能够跨越多个应用领域,而不局限于特定类型的软件开发。
设计模式与分析模式的区分:
- 特定领域的应用:分析模式针对特定的领域,如金融或航空航天,为该领域内的问题提供解决策略。
- 通用性与特定性:设计模式比分析模式更加通用,它们提供更广泛的解决策略,而不是局限于单一领域的问题。
设计模式的特性和目的:
- 改进设计:分析是由系统必须做什么来驱动的,而设计则是由系统必须如何达到其要求来驱动的。设计模式意在通过优化特定服务质量特性来改善和提升软件设计。
- 权衡与优化:在优化某些服务质量特性的同时,可能需要牺牲其他特性,设计模式就是在这种权衡中寻找最佳解决方案。
设计模式的应用层次: 设计模式可以应用于不同层次的设计抽象。在设计抽象层次中,每层都有其独特的模式类型和应用范围。
- 体系结构模式:这本书重点介绍的体系结构模式具有系统级的范围,提供了一种在整个系统层面上解决问题的方法,它们通常解决更广泛、更抽象的问题,如系统如何整体组织、系统各部分如何交互、数据如何流动等。
- 机制设计模式(GOF-4):在设计抽象的下一级别,机制设计模式适用于个别的合作关系。与体系结构模式相比,机制设计模式应用的范围更狭窄,通常针对特定的组件或组件之间的交互优化相同的服务质量(QoS)属性。例如,它们可能关注如何优化特定组件的性能、可靠性或可维护性。这些模式帮助设计者优化特定部分的设计,而不是整个系统的体系结构。
- 详细设计中的编程风格和最佳实践:在更细致的设计层面,设计模式通常不直接应用,而是更多的是使用编程风格(idioms)和最佳实践(practices)。编程风格特指在特定编程语言中解决特定问题的常见做法,而最佳实践则是广泛认可的、能提升代码质量和可维护性的一般性做法。这些通常关注实现细节,如代码组织、命名约定、编码风格等。
设计模式的类型: 本书介绍的模式主要是结构设计模式。这意味着,这些模式指导如何组织系统或系统的部分,以便可以应用行为策略来优化所需的服务质量(QoS)。结构设计模式的重点在于如何安排和构造系统的结构组件以及它们之间的关系,从而为后续的行为实现和优化提供良好的基础。然而,需要注意的是,并非所有设计模式都必须是结构性的。设计模式的范围远远超出了结构层面,还包括了行为设计模式等其他类型。例如,书籍《Doing Hard Time》[6]提供了一组行为设计模式,这些模式专注于如何“行为性地结构化”状态机,以优化状态机的工作方式。行为设计模式关注的是系统的行为特征,如状态转换、对象间的交互方式、算法的选择等,旨在改进或优化系统的行为特性。
结构设计模式通常关注以下几个方面:
- 系统组件的组织方式。
- 组件间的静态关系。
- 数据流和控制流的结构安排。
行为设计模式则侧重于:
- 系统的动态行为和交互模式。
- 对象如何协作完成任务。
- 状态变化和事件处理。
框架: 为了协同工作而特别定制的一系列相互关联的模式被称为框架。在基于框架的开发工作中,应用程序的大部分都是由实例化的框架提供的。这包括应用程序的核心内容,提供构建GUI元素、管理设备、处理并发、执行状态机等服务。开发者只需要构建系统的特有元素,其余全部依赖框架支持这个应用服务。
框架提供四种主要的使用策略:实例化、泛化、参数化和扩展,许多框架都使用这四种策略。
- 实例化:实例化策略时可以直接使用框架的某些方面,例如调度线程或执行状态机。
- 泛化:泛化策略采用框架的一个抽象元素并专门化它,添加新功能。例如,实时框架可能提供一个符合模型-视图-控制器(Model-View-Controller)风格模式的Sensor类,我们可以为特定设备子类化这个Sensor类并重写继承的方法。这是使用模式的非常常见的方式。
- 参数化:当框架提供参数化类时,例如在使用C++ STL容器时,你需要在实例化时提供实际的参数。
- 扩展:大多数框架都有特殊的地方,你可以插入部件来扩展框架。例如,插入一个CAN总线通信协议或一个HDLC(高级数据链路通信)协议。
框架的缺点是它们限制了你做事情的方式,而且框架比应用程序更难以设计和构建,尽管它们极大地简化了应用程序开发。尽管如此,框架是有效使用模式的典型示例,它们通过一套协同工作的模式提供了一个强大、灵活而且经过验证的解决方案的基础架构,使得开发者能够更加专注于应用程序的特定功能和业务逻辑。
3.3.2 设计模式的基本结构
根据Gamma等人的定义,一个设计模式主要包含以下四个重要方面:
-
名称:
- 名称为设计模式提供了一个“Handle”,便于引用和讨论模式。
- 通过命名,我们能够以明确、无歧义的方式引用模式,并用更抽象的词汇描述我们的设计结构。
-
目的:
- 目的描述了模式旨在优化的问题上下文和服务质量(QoS)方面。
- 它指明了模式适用的特定问题上下文,并明确了适用和非适用的情况。
-
解决方案:
- 解决方案即是模式本身,包含了模式中元素的定义及其相互作用。
- 接下来,我们将看到如何通过替换或继承这些元素,将模式具体实例化到应用中。
-
后果:
- 后果指出了采用模式的优点与缺点。
- 在选择一个模式时,我们需要进行权衡,并充分理解模式的优劣,以便有效应用。通常,这些优劣会以服务质量的改善或退化来表述,同时提供适用的问题上下文。
3.3.3 如何阅读本书设计模式
本节详细介绍了如何阅读本书中的设计模式。所有模式都采用统一的组织方式,以提升其可用性。主要内容包括: