第一章 并发和网络化对象
1.1 动机
1.2 并发和网络化软件的难题
采用网络化体系结构主要有三个理由:
- 协作和互联。
- 增强的性能、可伸缩性和容错。扩容、并行、减少单点失效。
- 成本效益。如高性能的硬盘控制器、大容量内存、增强的浮点性能。
1.2.1 难题 1:服务访问和配置
1.2.2 难题 2:事件处理
1.2.3 难题 3:并发
1.2.4 难题 4:同步
1.2.5 网络化软件的其他难题
- 依赖性
- 服务命名和位置选择
1.3 案例分析:设计一个并发的 Web 服务器
以 JAWS 框架为例,说明本书中的八个模式如何应用于产生一个灵活的、有效的 Web 服务器。
1.4 小结
第 2 章 服务访问和配置模式
2.1 Wrapper Facade (包装器外观模式)
包装器外观(Wrapper Facade)设计模式把现有的非面向对象的 API 所提供的函数和数据,封装在更加简洁的、健壮的、可移植的、可维护的和内聚的面向对象的类接口中。
- 例子 一个用于分布式登录服务的服务器,使用面向连接的 TCP 协议并发地处理多个客户端。
- 语境 可维护和可演化的应用程序,他们访问现有的非面向对象 API 提供的机制和服务。
-
问题
- 简洁的代码常常比冗长的代码更健壮,因为它更易于开发和维护。使用支持高级特性的面向对象语言,例如构造函数、析构函数、异常、垃圾回收等,可以减少普通编程错误。直接使用低层的、基于函数的 API 编程的开发人员容易重复地编写大量冗余的、易出错的软件。
- 软件产品如果可移植或者很容易移植到不同的操作系统、编译器和硬件平台,容易取得较大的市场份额。尽管复用现有的低层 API 可以减少某些开发软件的工作,但直接用低层 API 编写的应用常常是不可移植的。由于软件版本间缺乏源代码级或者二进制级的兼容性,即使在同一操作系统或者编译器的不同版本中使用低层 API 编程也可能是不可移植的。
- 改进软件可维护性可以减少软件生命周期的费用。直接食用低层的非面向对象 API 编写的程序常常难以维护。例如,C 和 C++开发人员常常把条件编译伪指令嵌入到应用程序源代码中,试图解决移植性问题。可是,如果在所有的点上都运用条件编译来处理与平台有关的变化,就增加了软件的实际设计复杂性。例如,与平台有关的细节分散到源文件的所有地方。
- 内聚的组件更容易学习、维护和增强。然而,低层 API 很少分组为内聚的组件,因为类似 C 这样的语言缺乏诸如类、名字空间或者包等特性,从而很难确认低层 API 的范围。使用费内聚的独立函数 API 编程,也使常用代码分散在整个应用程序中,使”插入”支持不同策略和机制的新组件变得困难重重。
- 解决方案 避免直接访问非面向对象的 API。对于非面向对象的 API 中的每组相关函数和数据,为他们创建一个或多个包装器外观类,把这些函数和数据封装在面向对象的包装器外观所提供的更简洁的、健壮的、可移植的和可维护的方法中。
- 结构
- 类
- 包装器外观
- 责任
- 用一个内聚的面向对象的抽象封装非面向对象的函数和数据结构
-
写作者
- API 函数
- 类
- API 函数
- 责任
- 通过一个定义良好的 API 提供一种服务
- 协作者
- xxx
-
动态特性 包装器外观将请求和参数传递给低层的 API 函数。
- 实现
- 标识内聚的抽象和现有的低层 API 之间的关系
- 把内聚的函数组聚合进包装器外观类和方法
- 创建内聚的类
- 把多个函数合并到一种方法之中
- 如果可能的话,自动化创建和销毁操作
- 选择间接的级别
- 确定在哪里封装任何与平台有关的变化
- 考虑允许应用程序受控访问实现细节
- 开发一种错误处理机制
- 定义相关的帮助者类(可选)
- 已解决的例子
- 已知使用
- 微软基础类(MFC Microsoft Fundation Classes)
- Java 虚拟机和 Java 类库
- 结论
- 优点
- 具体的、内聚的和健壮的更高级面向对象的编程接口。
- 可移植性和可维护性
- 模块行、可复用性和可配置性
- 缺点
- 功能丧失
- 性能降低
- 编程语言和编译器的局限性
- 优点
- 参考
- Facade(外观)模式。通常,Facade 在简单的 API 后面隐藏了复杂的类关系,而 Wrapper Facade 在丰富的面向对象的类后面隐藏了复杂的函数和数据结构 API 关系。
- Bridge(桥)。
- Adapter(适配器)。
- Decorator(装饰器)。