1. 程式人生 > >分析模式:可複用的物件模型 -- 責任模式

分析模式:可複用的物件模型 -- 責任模式

1          責任模式

這一章關注的重點是關係,以及怎樣為錯綜複雜的關係建立模型,另外,所有的插圖都來自原書(《Analysis PatternsReusable Object Models》),並遵循UML標準。

1.1    Party模式

在這一章中,首先我們接觸到是是Party模式,在進行系統分析和概念模型設計的時候,經常發現人和各種各樣的組織有著同樣的行為,例如,固定電話的計費可能是針對個人,也可能是一個單位;需要各種服務的時候,你可能求助於一個服務公司,或者服務公司一個特定的業務員。總之,因為人(Person)和組織(Organization

)表現上的一致性,如下圖所見,我們從中抽象出Party,作為Person Organization的抽象父類。

1.2    組織(Organization)的內部結構

第二步,如果我們把注意力轉移到組織(Organization)的內部結構,就會發現一些有趣的問題,通常最常見的一種結構是金字塔結構,因此建模時可能按照這樣的結構建立線性的模型,例如:

這樣的模型並沒有錯誤,但是有缺陷,首先不能滿足比較複雜的組織關係,更嚴重的是,一旦需要更多的層次關係,例如存在部門直接上下級關係以及區域附屬管理方式,必將引起整個模型的更改,對系統的影響可想而知,在這種情況下,最通常的改進措施是引入層次關係,如下圖所示:

通過增加新的關聯關係,可以靈活實現組織(Organization)之間的各種關係以及可能的變化。在上圖中,{hierarchy}是一個約束(constraint)來限定關係。

1.3        組織關係抽象

第三步,在一般的情況下,以上的模式已經足夠解決問題,但當這樣的層次和組織關係很多而且複雜時(超過兩種),例如現在流行的矩陣管理,就可以將關係本身抽取出來獨立處理,如下圖所示,作者此時考慮到組織結構的有效時段,所以加入了一個時間段屬性來記錄組織結構的存在時間。

請注意,在這個模式中,Organization Structure才是模式的核心,在系統中,由兩個Organization

的例項(分別充當parentsubsidiary),以及一個Type例項來說明該結構的型別。在這樣的結構中,可能存在許多的規則(Rule),這些規則可以根據情況分別處理:如果Type很多,而且規則主要跟Type有關,就分配給與Type相關聯;如果Type並不多,但主要根據Organization的子型別變化,就可以分佈到Organization的子型別中。

1.4    責任(Accountability)模式

第四步,從第一步看到,PartyPersonOrganization的抽象父類,因此把Party代入上面的模式(有點象我們小時侯代數裡常用的代入),正式形成責任(Accountability)模式。

1.5    知識層(Knowledge level)和操作層(Operational level)分離

出現這樣一種想法是考慮到以下情況:當Accountablity Type的數量比Accountability的數量多很多的時候,處理Accountablity Type的規則也變得更為複雜,要解決這樣的問題,就可以引入知識層和操作層的分離。

由下圖可見,用虛線隔離開的,就是知識層(Knowledge level)和操作層(Operational level),在這個模型中,知識層(Knowledge level)由三個類協作完成,它們分別是Accountablity TypeConnection RuleParty Type,在Connection Rule中定義合法的Party關係規則,並通過Accountablity TypeAccountablity進行建立時的合法性檢驗。它的另一個好處就是,可以將知識層的例項化獨立出來,作為操作層(Operational level)執行時的配置;換句話說,當知識層的規則改變時,系統的行為將被改變,而不需要任何其他程式碼的改動,這當然是一種比較理想化的情況。

 

由此想到,構建專家系統的設計思路也可以從這個模式得到一些啟發,這是筆者一時的感觸。

在原書中,如何實現這樣的模型提得比較模糊,但是筆者認為,可以將它們作為正常的模型來實現,兩個層次的區分只是表明它們各自擔負的任務和地位不同。知識層傾向於描述系統可能存在的各種形式,並設定判斷系統是否有效的各種規則;操作層則描述在這樣的配置下系統實際的行為。通過改變內在的配置來改變外在的行為,就是這個模式的目的。

由於這個模式的特點,改變系統行為時不必更改操作層的程式碼,但是,並不意味著改變系統行為連測試也不必要做。同樣,也需要除錯、配置管理。

作者也提到,這樣的模式用起來並不輕鬆,甚至在一般的系統中也不必要,但當你發現有必要用它的時候,別猶豫(感覺象用降落傘一樣)!

   知識級:知識級定義了操作級例項的具體配置,模型記錄控制著結構的各種通用規則,同時約束PARTY之間的的責任。

   操作級:模型記錄具體的團體,團體間的責任,以及責任的有效期間。

   知識級與操作級的劃分有效地分離了抽象與具體的,明確地指明瞭依賴關係。

2.示例

當你遇到紛繁複雜的關係不知如何處理時,可以考慮給這些關係"貼標籤"

讓我們以一個例子來說明貼標籤的作用:

現在的高校教師有很多是"雙肩挑",一方面擔任行政職務,另外一方面又在學校任課。作為行政領導的教師會有一些"下屬",這些下屬也是教師。例如院長下面有系主任、系主任下面又有教研室主任。其實,院長、系主任、教研室主任都是教師,都擔任課程。一個教師教多個學生,一個學生被多個教師教。為了描述他們之間的這種層次關係,我們可以通過以下UML圖來描述:

現在讓我們再引入更復雜的關係邏輯:除了普通本科學生外,還有研究生。而只有教授才可以帶研究生,不管該教授是否是院長、系主任還是教師。我們如何通過模型描述這種關係呢?如果某些學校內部的科研組織,其成員要跨學院,一個教師又分屬於不同的科研組織,如果……。可以看出來,隨著關係複雜程度的遞增,我們建模越來越困難。這個時候我們就可以請出"貼標籤"的法寶了。

當關系越來越多,越來越錯綜複雜時,依靠委派關係進行聚合就顯得力不從心,這個時候我們乾脆將所有委派都去掉,將"關係"集中進行存放。如下圖:

在關係檔案中儲存的就是關係"標籤",每個標籤上都記錄瞭如下屬性:委託方、責任方、之間的關係。有了這個關係檔案後,我們就可以避免在教師、學生、系主任等角色間使用委派標識了。如果用UML圖來表示這種改變的話就是:

團體是一個抽象型別,其子類包含各種型別的人員,團體持有對關係的一個委派,而關係中記錄了委託方、責任方以及關係型別。

如果你想查某個教師的關係網的話,就可以到關係表中查詢該教師作為委託方或責任方所對應的關係及其型別。或者你想檢視所有師生關係,就可以直接到關係表中查詢。通過將兩個不同成員間貼上"關係標籤",避免了引用造成關係難於擴充,難於處理的問題。

然而當前設計仍然存在一些問題,就是沒有嚴格的"約束"。在當前設計中,由於委託方與責任方的型別都是團體,所以對於委託方與責任方都是學生時,我們也可以給它賦上一個"師生關係",畢竟該模型對委託方與責任方的型別沒有任何約束力。為了使得模型更加完善,我們必須給"標籤"加上約束,不是什麼人都可以亂貼標籤的。於是我們重新設計模型如下:

模型被分成了操作級和知識級,在知識級中記錄了(1)都有什麼樣的標籤;(2)標籤的約束條件是什麼,什麼團體間才能具有該關係。

另外大家需要注意的是團體型別和團體並不是一一對應的,例如團體型別"教授",它有可能是院長、系主任也可能是教師。知識級的資訊對操作級進行約束、控制。當出現新的科研關係時,我們僅僅需要做的工作是(1)新增一個新的關係型別:科研關係,(2)為該關係新增約束條件:其委託方與責任方是除了學生、研究生外的其它團體(儘管研究生也搞科研,我們這裡暫不討論)。

通過貼標籤,我們就避免了增加委派關係帶來的麻煩。當然,如果你的模型比較簡單,只研究師生關係的話,就大可不必這麼麻煩。

再來看看《分析模式(中文版)》第3章39頁(英文版第41頁)的一個例子,該例子用來記錄病人到醫院看病,記錄檢查的觀測結果。看病的測量太多了,肺活量、血壓、心率,單位可能相同也可能不相同。我們無法通過委派關係讓一個病人持有所有檢查的引用。況且當你看到一個檢查結果是"A"時,也無法知道究竟是血型是A,還是評估等級為A級。因此我們將患者和測量結果間貼上標籤,標籤上記錄如下資訊:(1)患者姓名(2)測量內容(3)數量。當患者檢測完後,手中只要持有一組標籤就行了,而不用去管什麼單位不單位的。究竟數量是否正確那是知識級所需要做的事情了。如下圖:

這樣,患者和數量間就被貼上了測量的標籤,而該標籤的使用必須滿足觀測型別中所規定的約束條件。

參考文件:

原文參照《Analysis Patterns:Reusable Object Models》,Chapter 2,Martin Fowler

《分析模式——可複用的物件模型》(Martin Fowler著)[機械工業出版社]