淺談設計模式在建安系統中的應用

鴨脖發表於2014-03-31

東湖專案接近尾聲,一直想寫一下對於該系統設計的感悟,今天就在這裡寫一寫吧。

         首先,評價一個系統的好壞,在我的心裡有三個標準:第一是可擴充套件性,我把它放在第一位,因為沒有哪個專案是不需要不斷修改的,這是事物客觀發展的必然結果,因為從哲學上講,事物的變化是一直髮生著的,所以系統的不斷擴充套件是真理客觀決定的結果。第二是穩定性,當然如果你從使用者的角度出發,這顯然才是最重要的,不過誰讓我們是程式設計師呢,而且我也不是測試人員,編碼人員對於某種功能或者模組的疏漏是在所難免的,當然穩定性的提高很大程度上需要測試人員的努力。第三便是效能,雖然它受硬體的很大影響,但是效能的優化途徑不僅僅侷限於硬體的升級,通過分散式高併發等的設計,或者通過伺服器減壓,如反爬蟲,增加過濾器等優化手段,也可以使得系統效能得到很大提升,這直接影響到使用者體驗。當然這和本次專案的聯絡不大,而且作為一名架構與編碼的菜鳥,即“軟體偽工程師“,上述方面我也並沒有很多實際經驗。不過想得到才能做得到嘛。

         東湖專案採用的是網路上比較流行的通用許可權管理系統Framework,是基於此框架的二次開發。其實涉及到的技術難點也不多,只不過由於其資料層結構略複雜,業務層功能略多,而且使用者的特殊性,使得專案週期‘略’長。Framework框架也是將系統分為資料層,邏輯層和表現層,結構很清晰,其中對於各種物件,模組的封裝也很到位,有很多值得我學習的地方。首先我們看一下資料層的結構,它的類圖大致如下圖:


這種設計充分地考慮了可擴充套件性。之前也用過O/RMapping的工具和框架,像Hibernate等。之前只是去用,去寫xml,也沒考慮過自己去寫一個類似這樣的框架。其實我現在覺得那些流行的框架的實現原理也就這麼回事,無非是增加了一個xml解析的過程。上面的這個結構就是原理所在。可以發現,這種設計滿足了多種資料庫的要求,可以自由擴充套件。那麼,在上述的設計中,用了什麼設計模式呢?從系統中找設計模式是一個很有意思的過程,就彷彿是在一堆沙子中找金子,在一堆水泥中找鋼筋。我的第一印象是簡單工廠,但是裡面又沒有工廠類,那麼是什麼呢?工廠?還是抽象工廠?首先簡單工廠模式中沒有抽象類,只有一個含有公用方法的基類,它是根據客戶端傳入的引數case來判斷應該生產哪種Product。就好比蘋果公司的工廠(當然是富士康),首先他們有一個iphone的基本設計圖紙,這就好比是基類,當你傳入iphone4s 時,就會生產iphone4s,傳入iphone5時就會生產iphone5 。而工廠模式則是將每種ConcreteProduct對應於一個工廠,就好比現在iphone4s 只由iphone4s工廠來生產,iphone5 只由iphone5工廠來生產。這樣的好處是當iphone8開發出來的時候,我們不需要再去像簡單工廠一樣去修改系統內部的case結構,而只是在客戶端更改工廠的型別,滿足開放-封閉原則。而抽象工廠如其所言,就是工廠不是專注於一種產品,而是專注於多種相互之間存在聯絡的產品,就好比iphone4s工廠不僅生產iphone4s,而且還生產iphone4s的充電器,iphone5工廠不僅生產iphone5,而且還生產iphone5的充電器。上述設計其實是用了簡單工廠模式,但是為什麼沒有工廠類呢?其實產品類基類本身就是工廠類(這裡雖然它是一個抽象類,但是它並不是工廠模式,它抽象的原因是為了實現不同資料庫的訪問),在DataProvider的建構函式中,根據Web.config配置檔案來決定構造哪一種DataProvider。這個基類最主要的作用是根據從資料庫取得的域來將其構造成物件並且放回,.net框架的函式代理很好的配合這一設計並且將其實現,函式代理在C++中就是函式指標,在java中可以通過反射機制或者Interface來實現,其實DataProvider中也可以不使用函式指標,也可以直接通過呼叫來實現,但是通過使用函式指標形式要更為優雅一些。上述設計中還包含一種設計模式,大家仔細觀察,裡面有instance屬性,而且是private static型別的,對沒錯,那就是單例模式。因為該系統只能設定一個資料庫(非分散式),所以它按照這種設計模式保證該DataProvider只能有一個,所以綜合來說,該種設計是單例模式和簡單工廠模式的融合,其中工廠類是產品類基類自身。

         第二個我要說的,是他們封裝條件查詢的方式。如果每次查詢都重寫一下條件查詢前面的sql語句,那就顯得臃腫很多,而且在這種條件查詢幾乎隨處隨時可見的系統。那麼解決辦法就是單獨將條件查詢封裝起來,然後通過引數傳遞給非條件查詢邏輯模組來進一步查詢。該系統採用的方式是將SQL 條件查詢封裝成QueryParam這個物件,該物件中包含了條件查詢的各種屬性,包括where,order by,如果採用分頁顯示,它還包括pageindex,配合Pager一起使用。在使用的時候,我們首先構造這樣的一個物件,然後將其傳遞給DataProvider中構造sql並且進行查詢的模組,該模組根據該物件中各個域的值來構造sql,最後查詢出結果並且構造出物件且返回。這裡面也有一些問題,比如當你分頁顯示時,兩次倒置可能就使得倒排產生混亂,如這個框架就沒有很好的解決這一點。

         第三個我要說的,就是許可權管理。許可權管理說白了其實就是是否讓某個功能的User Interface,如按鈕,超連結等等,顯示給當前擁有某種許可權的使用者。當然許可權是由超級管理員來設定的,需要使用者自己配置,所以許可權要基於角色,我們根據角色來設定是否將該Interface暴露給使用者,許可權的設定無非就是將使用者對應於特定的角色。當然這種設計是很靈活的,只要你資料庫表的某些欄位能體現這些關係,都可以,只是優雅不優雅的問題了。

         先說這麼多了,當然這個過程中涉及到的技術細節有很多,那些都只能算作經歷罷了,真正有營養的還是上面講的那些東西,這是skeleton,這才是經驗。架構和設計是一門很深奧的學問,也是一門很文藝範兒的學問,既要像學習數學一樣靈活,也要像畫畫一樣優雅,這其中的知識,還需要我在今後的日子中不斷揣摩。

 

相關文章