(零雨其蒙原创 转载请注明)
2007
						
				
				
						年
						
								3
						
				
				
						月
						
								14
						
				
				
						日星期三
						
								
								
								
						
				
		
		
				第
				
						37
				
				章
				
				
				使用模式设计持久性框架
		
		
				持久性对象
		
		
				
						
								                
								Persistent Object
						
				
				
						是指需要持久性存储的对象。
						
								
								
						
				
		
		
				框架
		
		
				好莱坞原则
				
						
						
				
		
		
				
						即“不要给我们打电话,我们会打给你”。意思是,用户定义的类(例如新的子类)将从预定义的框架类接收消息。这通常是通过实现超类的抽象方法来实现的。
						
								
								
						
				
		
		
				
						
								
										 
								
						
				
		
		
				
						
								
										
												   
										
								
						
						
								这种方式就是说框架(容器)来调用用户自定义的类,而不是相反,其实就是
								
										Rod Johnson
								
						
						
								所谓的“
								
										IoC
								
						
						
								”,而被
								
										Martin Fowler
								
						
						
								进一步解释的“依赖注入”(
								
										DI
								
						
						
								)。
								
										
												
												
										
								
						
				
		 
		
				
						
								
										 
								
						
				
		
		
				线程安全
				
						
						
				
		
		
				
						
								    
						
				
				作为技术服务子系统,持久性服务(其他的很多服务也一样)应该被设计成线程安全的。
		
		
				关键思想
		
		
				映射(
				
						mapping
				
				)
				
						
						
				
		
		
				
						
								 
								
										   
								
						
				
				
						在类和持久性存储(例如,数据库中的表)之间,对象属性和记录的域(列
				
				,字段)之间必须有某种映射关系。也就是说,在这种模式之间必须有模式映射(
				
						
								schema mapping
						
				
				
						)
				
				
						。
						
								
								
						
				
		
		
				
						
								 
						
				
		
		
				模式映射在
				
						Hibernate
				
				和
				
						iBatis
				
				等现代框架中都是包含在
				
						XML
				
				文档中的,在
				
						Java
				
				中对象由
				
						POJO
				
				来担当,
				
						Larman
				
				已经说得足够详细。
		
		
				
						
								 
						
				
		
		
				对象标识(
				
						object identity
				
				)
				
						
						
				
		
		
				
						
								   
								
										  
								
						
				
				
						为了方便将记录与对象联系起来,确保没有不适当的重复,记录和对象必须有唯一的对象标识。
						
								
								
						
				
		
		
				
						
								 
						
				
		
		
				
						
								 
						
				
				数据库中会有完全相同的两条记录吗?按理来说应该没有吧(正常情况应该没有,也可能某个表没有设关键字?)
		
		
				
						
								 
						
				
		
		
				数据库映射器(
				
						database mapper
				
				)
				
						
						
				
		
		
				
						
								          
						
				
				
						负责具体化和虚化的纯虚构数据库映射器。
						
								
								
						
				
		
		
				
						
								               
						
				
		
		
				具体化和虚化(
				
						materialization and dematerialization
				
				)
				
						
						
				
		
		
				
						
								          
						
				
				
						具体化是指将持久存储中数据的非对象表示(例如记录)转换为对象。虚化是指与具体化相反的动作,也称为钝化(
						
								passivation
						
				
				
						)。
						
								
								
						
				
		
		
				
						
								 
						
				
		
		
				缓存(
				
						cache
				
				)
				
						
						
				
		
		
				
						持久性服务为提高性能缓存具体化后的对象。
						
								
								
						
				
		
		
				
						
								 
						
				
		
		
				对象的事务状态(
				
						transaction operation
				
				)
				
						
						
				
		
		
				
						
								         
						
				
				
						就对象与当前事务而言,了解对象状态是有用的。例如,了解哪些对象已经被修改以便决定是否需要将它们存入持久存储中。
						
								
								
						
				
		
		
				
						
								 
						
				
		
		
				事务操作(
				
						transaction operation
				
				)
				
						
						
				
		
		
				
						提交和回滚操作。
						
								
								
						
				
		
		
				
						
								 
						
				
		
		
				滞后具体化(
				
						lazy materialization
				
				)
				
						
						
				
		
		
				
						并非一开始就具体化所有对象,只有当需要时才具体化特定实例。
						
								
								
						
				
		
		
				
						
								 
						
				
		
		
				虚代理(
				
						virtual proxy
				
				)
				
						
						
				
		
		
				
						
								    
						
				
				
						滞后具体化可以通过使用
				
				
						
								(
						
				
				
						称为虚代理的
				
				
						
								)
						
				
				
						智能引用(
						
								smart reference
						
				
				
						)来实现。
						
								
								
						
				
		
		
				
						
								 
						
				
		
		
				模式
		
		
				将对象表示为表
				
						
						
				
		
		
				
						
								   
								
										 
								
						
				
				
						将对象表示为表(
						
								Representing Objects as Tables
						
				
				
						)模式
						
								[BW96]
						
				
				
						建议为每个持久对象类在关系数据库中定义一个表。包括基础数据类型(
						
								number
						
				
				
						,
						
								string
						
				
				
						,
						
								boolean
						
				
				
						等)在内的对象属性将映射为列。
						
								
								
						
				
		
		
				
						
								 
						
				
		
		
				如果是这样,或许就要改变传统的从设计数据库开始设计系统了,数据库中的表是通过持久性对象来确定的。
		
		
				
						
								 
						
				
		
		
				
						
								 
						
				
		
		
				对象标识符
				
						
						
				
		
		
				
						
								  
								
										  
								
						
				
				
						对象标识符(
						
								Object Identifier
						
				
				
						)模式
						
								[BW96]
						
				
				
						建议给每个记录和对象(或对象的代理)分配一个对象标识符(
						
								OID
						
				
				
						)
						
								
								
						
				
		
		
				
						
								 
						
				
		
		
				
						动机
				
				
						:
				
				为了确保记录的重复具体化不会导致重复对象,需要有关联对象和记录的一致性方法。
		
		
				
						
								 
						
				
		
		
				
						
								 
						
				
		
		
				数据库映射器模式
				
						
						
				
		
		
				
						
								          
						
				
				
						数据库代理(
						
								Database Broker
						
				
				
						)
						
								[BW95]
						
				
				
						模式,即创建一个类来负责对象的具体化、虚化和缓存。该模式也被称为数据库映射器(
						
								Database Mapper
						
				
				
						)模式
						
								[Fowler01]
						
				
				
						。
						
								
								
						
				
		
		
				
						
								 
						
				
		
		
				
						
								 
						
				
		
		
				
						Template Method
				
				模板方法(
				
						GoF
				
				)
				
						
						
				
		
		
				
						该模式的思想是,在超类中定义一个方法(模板方法),超类定义了算法的框架,其中既有固定部分也有变化部分(
				
				就是那些可以被子类重写的部分)。模板方法调用其它一些方法,这些方法中有些可能会被子类覆写。因此,子类可以覆写(重写
				
						override
				
				
						)这些变化的方法,以此在变化点增加自己特有的行为。
						
								
								
						
				
		
		
				
						
								 
						
				
		
		
				
						
								 
						
				
		
		
				
						
								           
						
				
				具体实现还会引入回调函数,钩子函数这样的技术,等有空我会就
				
						C++
				
				,
				
						Delphi
				
				,
				
						Java
				
				和
				
						C#
				
				来分析一下这个主题。
		
		
				
						
								 
						
				
		
		
				
						
								 
						
				
		
		
				缓存管理模式
				
						
						
				
		
		
				
						
								
										 
								
						
				
				
						缓存管理(
						
								Cache Management
						
				
				
						)模式
						
								[BW96]
						
				
				
						建议由数据库映射器负责维护缓存。如果每个持久性对象使用不同的映射器,那么每个映射器就可以维护自己的缓存。
						
								
								
						
				
		
		
				
						
								 
						
				
		
		
				
						
								 
						
				
		
		
				事务状态
				
						
						
				
		
		
				
						
								              
						
				
				当执行删除或保存操作时,都是先将持久性对象转换成适当的状态(就是由数据库中将对象提出将其状态设为
				
						Old Clean
				
				),然后执行提交或回滚方法时,再真正修改数据库。这和
				
						DBMS
				
				做的事务管理原理差不多,中间做一个过渡,就好比要把一个文件从
				
						C
				
				盘转移到
				
						D
				
				盘,使用剪切,将文件保存在内存中(文件的状态改变了,位置从硬盘变成了内存),然后当在
				
						D
				
				盘执行粘贴命令时,才会真正将文件转移过来。这里面的内存就相当于
				
						Old Clean
				
				状态。
		
		
				
						
								 
						
				
		
		
				
						
								 
						
				
		
		
				
						State
				
				状态模式(
				
						GoF
				
				)
				
						
						
				
		
		
				
						
								问题:
						
						对象的行为依赖于它的状态,而它的方法中包含能够反映依赖状态的条件动作的
						
								case
						
						逻辑。是否存在替代条件逻辑的方法?
				
				
						
								解决方案
						
						:给每个状态创建状态类,并实现一个公共的接口。将语境对象中的依赖于状态的操作委派给其当前的状态对象。确保语境对象总是向反映其当前状态的状态对象。
				
		 
		
				
						
								 
						
				
		
		
				听上去有些拗口,但时间上没那么复杂,其实还是使用的接口和多态(好多
				
						GoF
				
				模式用的都是这种方法),给持久性对象增加一个状态属性(类型是接口),然后与状态对象接口形成对应关系,存在不同的状态类来实现这一接口,根据持久性对象地状态属性被赋值为哪个具体的状态类,来决定调用哪个状态类的方法(多态)。详细情况看第
				
						461
				
				页的图就可以了。
		
		
				
						
								
										P461 
								
						
						
								在性能方面,这些状态对象实际上是无状态的(没有属性)。因此,这些类只需要有一个实例(每个类都是单实例类)。例如,数以千计的持久性对象可以引用同一个
								
										OldDirtyState
								
						
						
								实例。
								
										
										
								
						
				
		 
		
				
						
								 
						
				
		
		
				
						
								 
						
				
		
		
				
						Command
				
				命令模式(
				
						GoF
				
				)
				
						
						
				
		
		
				
						
								问题:
						
						如何处理需要诸如排序(优先级)、排队、延迟、记录日志或重做等功能的请求或任务?
				
				
						
								解决方案
						
						:为每个任务创建一个类,并实现共同的接口(这句话一出,往往就意味着使用多态)。
				
		 
		
				
						
								 
						
				
		
		
				
						
								
										P462 
								
						
						
								动作成为了对象,因此可以被排序、记录日志、排队等。
								
										
										
								
						
				
		 
		
				
						
								 
						
				
		
		
				
						
								 
						
				
		
		
				虚代理
				
						
						
				
		
		
				
						
								
										Virtual Proxy
								
						
						
								是其他对象(
								
										real subject
								
						
						
								)的代理,当它第一次被引用时具体化该对象。
								
										
										
								
						
				
		 
		
				
						
								 
						
				
		
		
				
						
								 
						
				
		
		
				在
				
						Java
				
				中,可以使用动态代理实现虚代理。(需要再好好看看
				
						Java
				
				的动态代理)
		
		
				
						
								 
						
				
		
		
				
						
								 
						
				
		
		
				
						
								 
						
				
		
		
				第
				
						38
				
				章
				
						UML
				
				部署图和构件图
		
		
				部署图
		
		
				
						
								    
						
				
				部署图表示的是,如何将具体软件制品(例如可执行文件)分配到计算节点(具有处理服务的某种事物)上。部署图表示了软件元素在物理架构上的部署。
		
		
				
						
								 
						
				
		
		
				构件图
		
		
				
						
								 
						
				
				构件
				
						
						
				
		
		
				
						
								
										Component
								
						
						表示封装了其内容的系统模块,它在其环境中的表现形式可以被替代。构件通过所提供的和所需要的接口定义了其行为。同样,如果构件作为类型,那么它的一致性是通过这些所提供的和需要的接口来定义的。
						
								[OMG03b]
						
				
		 
		
				
						
								 
						
				
		
		
				
						
								 
						
				
		
		
				
						
								 
						
				
		
		
				
						
								 
						
				
		
		
				第
				
						39
				
				章
				
				
				架构的文档化:
				
						UML
				
				和
				
						N+1
				
				视图模型
		
		
				软件架构文档
				
						SAD
				
		
		
				
						SAD
				
				描述有关架构的总体想法,包含架构分析的关键决策。
		
		
				从本质上讲,
				
						SAD
				
				是对架构性决策(例如技术备忘录)的总结以及对
				
						N+1
				
				架构视图的描述。
		
		
				
						
								 
						
				
		
		
				
						
								 
						
				
		
		
				
						N+1
				
				(或
				
						4+1
				
				)视图模型
		
		
				
						
								              4+1
				
				视图模型
				
						4
				
				个视图分别是:逻辑、进程、部署和数据。“
				
						+1
				
				”视图指的是用例视图。
		
		
				
						
								 
						
				
		
		
				架构视图的细节
		
		
				逻辑视图
				
						
						
				
		
		
				进程视图
				
						
						
				
		
		
				部署视图
				
						
						
				
		
		
				数据视图
				
						
						
				
		
		
				安全视图
				
						
						
				
		
		
				实现视图
				
						
						
				
		
		
				开发视图
				
						
						
				
		
		
				用例视图
				
						
						
				
		
		
				
						
								 
						
				
		
		
				
						
								准则
								
										
										
								
						
				
				
						
								
										
												   
										
								
						
						
								不要忘记动机!
						
						也就是要把为什么这样设计写清楚!
				
		 
		
				
						
								 
						
				
		
		
				
						Struts
				
				框架用到的模式
		
		
				
						ActionServlet
				
				是访问表现层的外观。
		
		
				
						ActionServlet
				
				和
				
						Action
				
				对象的设计采用了命令处理器模式。
				
						ActionServlet
				
				扮演了命令处理器角色,接收请求并将它们映射为
				
						Action
				
				(
				
						Action
				
				是
				
						
								Command
						
				
				
						对象
				
				)对象,
				
						Action
				
				对象负责执行请求。
				
						
								  
						
				
		
		
				
						ActionServlet
				
				是前端控制器,处理请求的初始接触点。
				
						Action
				
				对象是业务委派——向“业务”或领域层服务委派的抽象。
		
		
				
						Action
				
				对象也扮演了适配器的角色,将框架调用适配为领域层对象的接口。
		
		
				
						
								    ActionServlet
				
				实现了模板方法模式,
				
						process
				
				是模板,
				
						processXXX
				
				是钩子方法。
		
		
				
						
								 
						
				
		
		
				
						
								 
						
				
		
		
				第
				
						40
				
				章
				
				
				迭代式开发和敏捷项目管理的进一步讨论
		
		
				
						
								 
						
				
		
		
				迭代开发各阶段的目标
		
		
				
						
								
										    
										P487 
								
						
						
								UP
						
						
								是用例驱动的
						
						
								,这意味着工作是围绕用例的实现来组织的。也就是说,每次迭代都要实现若干个用例或者用例场景(如果用例太复杂不能在一次迭代中完成)。
								
										
										
								
						
				
		 
		
				
						
								 
						
				
		
		
				
						
								 
						
				
		
		
				
						第一次迭代
				
				选择要选择重要用例的简单场景或理想路径场景(主成功场景)。
		
		
				
						在细化阶段
				
				需要处理与该用例相关的具有重要架构意义的不同需求,这要可以迫使团队接触到架构的各个方面:主要层、数据库、用户界面、主要子系统之间的接口等。这就有助于及早创建跨越系统众多部分的
				
						“广泛但浅显”
				
				
						的实现
				
				——这是细化阶段的常见目标。
		
		
				
						
								 
						
				
		
		
				
						
								 
						
				
		
		
				
						
								 
						
				
		
		
				
						
								 
						
				
		
		
				
						
								本书心得:
						
						终于把这部巨著看完了,不过第
						
								1
						
						章到第
						
								9
						
						章都没做笔记,只是在一篇总结中对用例、领域模型等内容做了总结和讨论,但是没有从大局观上来记述
						
								UP
						
						各个阶段需要怎样做,持续的时间和创建的制品,等读第二遍时,从宏观角度在记述一遍,总结一下。另外很多模式、原则都需要在实践中去进一步理解,因此这不是看一遍就
						
								over
						
						的书。另外这也是一本入门书,下一步我会阅读一些本书提到的重要文献,对各个问题进行深入的探究,并配合实践(以
						
								J2EE
						
						和
						
								Delphi
						
						为工具和案例研究)。