零雨其蒙's Blog

做优秀的程序员
随笔 - 59, 文章 - 13, 评论 - 58, 引用 - 0
数据加载中……

零雨其蒙《UML和模式应用》学习笔记(十一)


(零雨其蒙原创 转载请注明)
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 为工具和案例研究)。

posted on 2007-03-20 15:00 零雨其蒙 阅读(533) 评论(0)  编辑  收藏 所属分类: 学习笔记


只有注册用户登录后才能发表评论。


网站导航: