主要解决如何将数据访问从应用中分离出来的问题。只要和数据库打交道的应用,都会碰到这个问题。传统的C/S架构应用大多将数据访问和应用的代码糅合在一起,主要有几个方面的问题:
o 与具体的数据库技术紧密耦合,比如我们公司的产品是基于SQL Server的,现在就很难切换的Oracle中去,更不要说是以后的新技术——XML数据库或面向对象数据库;
o 应用与数据模型紧密耦合,缺少弹性。
o 难以优化,每个模块都是由不同的程序员写的,但是不是每个人都擅长数据库的开发,所以造成程序的效率低下,而要优化这些代码成本颇为昂贵;
o 不便于维护,当程序出现问题的时候,不容易发现问题的来源——来自业务逻辑还是数据访问逻辑;
这一部分介绍了四种模式:
o 数据访问器
o 主动域对象
o 对象/关系映射
o 层
第一章:数据访问器(Data Accessor)模式
简述
“在单一组件内封装物理数据访问细节,只公开逻辑操作。应用程序代码保留底层数据模式的知识,但是与数据访问只能分开。”
封装原则
o 公开逻辑操作,封装物理操作——比如不直接使用SQL语句而用逻辑操作。
o 公开逻辑资源,封装物理资源——可以充分利用资源,例如连接的共享。
o 封装平台细节——平台无关性。
o 封装优化细节——将优化的弹性放到数据访问器中,而不是应用代码中,这样可以统一的优化。
适用性
o 需要对应用程序逻辑隐藏物理数据访问的复杂性和平台问题。
o 在底层物理数据库驱动程序所提供的语义职位,需要管理另外的语义。比如应用程序级的锁定机制。
o 需要定义多个数据访问实现并在运行时从中选择。
优点
o 清晰的应用程序代码——充斥着数据访问细节的应用程序代码难以阅读和维护,使用数据访问器,可以让应用程序代码更加集中到它自身的业务逻辑上。
o 新数据库特性或平台的采用——如果数据访问代码分布到整个系统中,如果要使用新的数据库特性(例如从SQL Server平台切换到Oracle平台)就要浏览和修改整个系统的代码,而使用数据访问器可以将这种细节封装到一个组件中。
o 结合优化策略——调整应用程序性能时,数据访问代码常常是主要的分析焦点,同样的使用数据访问器就可以一次引入优化策略而作用于整个系统。
o 可交换的物理数据访问实现。
缺点
o 限制了应用程序对数据访问的控制——要求数据访问器设计要有足够的通用性。
策略
o 定义通用的逻辑操作——一方面要注意通用性;另一方面也不要引入不必要的复杂性,可以通过研究用例来解决这个问题。我觉得经验的积累也很重要。
o 留下优化和改进的位置——在开发过程中经常要牺牲功能以保证进度。
o 防止应用程序的抵消用法。
实例化
o 单件(Singleton)数据访问器实现。
o 初始化和参数传递——缺点是需要在类的构造函数和操作定义一个额外的参数。
o 数据访问器工厂。
第二章:主动域对象模式
简述
在相关的域对象实现中封装数据模型和数据访问细节。主动域对象使应用程序代码避免了与数据库的任何直接交互。
主动是指域对象不只是简单的表示数据,还公开了逻辑操作(初始化、刷新、保存、列表),为它们的数据完成大多数相关的数据库交互。操作的命名使用领域的术语命名。
适用性
需要对应用程序逻辑隐藏物理数据模型和数据访问的复杂性。
需要在单个组件中封装关于某个域概念的所有数据模型和数据访问细节。
需要对应用程序逻辑隐藏数据模型的不一致性和晦涩性——遗留数据的适配。
优点
清晰的应用程序代码
解耦应用程序代码和数据模型
把相关的数据访问代码组织到单个组件中
缺点
数据访问分布在多个域对象中
限制了应用程序对数据访问的控制
第三章:主动域对象模式
简述
在单个组件中封装域对象和关系数据之间的映射。对象/关系映射同时把应用程序代码和域对象从底层的数据模型和数据访问细节中分离出来。
适用性
需要向应用程序逻辑和域对象隐藏物理数据模式和数据访问的复杂性。
需要在单个组件中封装域对象映射,以便在数据模型发生变化时可以不修改应用程序代码或者域对象定义。
需要从域对象映射到多种数据模型而不修改应用程序代码或域对象定义的通用性。
权衡
依赖于另外的商品化产品
优点
清晰的应用程序代码
映射到可替换的数据模型
缺点
限制了应用程序对数据访问的控制
第四章:层
简述
把处理数据访问问题的正交应用程序特性叠放在递增的抽象层中。
适用性
需要分离数据模型、数据访问细节、域对象映射,或者其它准备独立修改的正交特性。
都要定义多个递增的软件抽象层以简化开发和维护工作。
需要建立原型或者使用存根或简化的层实现逐步构造系统,并在以后的开发过程中填入更加灵活或者优化的实现——先让它工作起来、然后让它工作得更好。
优点
软件设计分解
数据访问特性模块化
数据访问细节封装
多层实现的可插接性
缺点
曾交互和初始化的复杂性
小结
解耦模式这一部分介绍的四个模式主要解决的是将数据的持久化从应用程序逻辑中分离出来。这样做的主要意义是使应用程序代码变得清晰,把主要主要精力放在需求和功能方面;另一方面也实现了持久层的可替代性——依赖于接口而不依赖于实现;通过不同层次的抽象还可以保证数据访问代码的质量——从而保证系统的性能影响。
数据访问器模式解决的是底层的东西——数据访问细节的抽象。
主动域对象和对象/关系映射两个模式解决的都是如何将数据模型从应用程序代码中分离出来这个问题,但是它们采用了不同的方式实现对象模型和关系模型的映射,只不过一个是分散的,一个是集中的;一个自力更生、一个依赖于现成的产品(不是绝对的)。
层这个模式给出了进一步分解这个问题的方案——将抽象划分为若干层。