(零雨其蒙原創 轉載請注明)
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
為工具和案例研究)。