軟體開發的天空


SINCE 2004

最新回應

之前曾經在 Facade Pattern 一文中提到Data Access Layer實踐Façade Layer的觀念,這是對於客戶端呼叫時提供了穩固以及不易變異的介面。

不過這是對於客戶端,也就是外部使用這個物件時的觀點,那麼今天我想可以進一步探討這顆Data Access Layer的套件在內部怎麼樣設計會比較好些。

假設今天老闆要我們設計一個銷售系統,我們打算將銷售系統中的Data Access Layer抽離出來(抽離出來的理由應該不用再贅述了),我們需要考量下面的因素:

日後這個銷售系統可能搭配SQL Server或者Access甚至其他的儲存裝置來販售,所以我們必須將Data Access Layer的彈性與擴充性功能考量進去。

也就是說,我們在程式中使用到這個套件的時候,最好可以不知道我們現在是聯結到SQL還是Access的裝置上,那麼日後就只要變更Data Access的套件,高階的商業邏輯套件可以原封不動。

經過思考之後,我們可以利用下面這樣的方式來達到目的。

看起來這樣做是沒什麼問題的,我們只要依此類推,再增加要取得DataSet、DataReader、Scalar等回傳型態的函式,然後功能依照平台的不同導到各自負責的函式去處理就好了。但是,要是增加了ㄧ個平台呢?比如說是用Oracle連結的儲存裝置呢?

那我們只好回去打開這顆套件,然後加上負責處理Oracle的函式以及在負責分派的四個函式加上屬於Oracle的分,每增加一個平台選項時必須異動到的地方有八處,如果這顆元件功能再強化一些細節的功能的話,只會更複雜而以。

會不會有點糟糕?

再思考下ㄧ個問題,資料庫平台的數量不算太多,算來算去也就那幾種,所以用這種作法勉強可以接受,但是如果這樣的作法用在其他的議題上,萬一衍生的種類來個十項,這支程式大概要又臭又長又難維護了……

或許我們可以用下面的作法試試看。

我們設計了ㄧ個Icommand的介面,定義了執行資料庫的幾個函式與屬性,然後讓其他類別去實做它。我們可以選擇先實做負責處裡SQL平台的物件,因為這是我們的老闆要我們先出這個版本的產品。

在SOLCommand類別裡,我們才真正實做了幾個處理SQL資料庫工作的函式。接下來如果我們要實做處理Access的類別時,只要新增一個類別OleDBCommand然後實做Icommand介面就好。

F2

上面的作法好處是什麼呢?

不管我要增加幾個衍生的平台,都不會有機會去碰觸到已經寫好的程式碼,我們都知道,當系統隨著時間增長,會藏下許多我們都不知道的地雷,所以能夠不去修改到舊有的程式碼是最理想的,上面的做法可以滿足這樣的需求。

接下來我們有另一個課題要解決,就是不讓客戶端知道最後實做的到底是那個平台的類別,對使用這顆物件的客戶端程式碼來說,它面對的永遠都只是Icommand介面。

F2

我們讓CommandFactory物件來決定最後實做的類別究竟是哪一個,不管最後是要實做SQL還OLEDB,都讓CommandFactory來面對客戶端程式,然後用CreateCommand來回傳Icommand物件。

如同上面的範例,對客戶端來說,將永遠不會知道究竟是使用了哪種資料庫物件,它面對的只有一個類別跟一個介面,CommandFactory與Icommand,不論後面究竟已經衍生了幾百種類別。換句話說,我們可以在客戶端程式不知情的情況下擴充甚至更換掉商業邏輯的元件,是不是很棒呢?

這樣的做法特別適用於企業邏輯時常需要的更換或擴充的系統,那麼就可以在不變動到舊有程式下達到擴充的目的。

最後,這樣的模式可以算是Factory Pattern 加上 Strategy Pattern的混合應用。

在這個例子中,Factory指的自然就是負責建立符合實作介面的CommandFactory,而Strategy指的是利用客戶端只相依於一抽象介面的特性下,達到彈性替換演算法的功能。


回應

目前沒有回應.

*標  題:

*姓  名:

  電子郵件: (將不會被顯示)

  個人網頁:

*回應

登入後使用進階評論

Please add 4 and 3 and type the answer here: