2011/05/18

[Design Patterns] 抽象工廠模式(Abstract Factory)

參考:大話設計模式
型態:創建型模式/生成模式。
定義:提供一個建立一系列相關或相互依賴物件的介面(接口) ,而無需指定他們具體的類別。
使用時機: 需要一組可以隨時抽換的元件,並且希望可以簡單的一次抽換
結構圖:
來源 
2011-5-17 下午 11-51-20
說明:
「AbstractProductA」和「AbstractProductB」是兩個抽象產品,它們都有多種不同的實現。
「Product 」為抽象產品的具體實現。
「AbstractFactory 」抽象工廠介面,它裡面應該包含所以的產品建立的抽象方法。
「 ConcreteFactory」具體工廠。

========================================================================================================
狀況:有一個專案,對於資料的存取,我們希望實現多資料庫,不侷限於某一個資料庫。
程式碼範例(模擬)
設定兩個類別表示為資料表
2011-5-18 上午 12-39-52

撰寫 IUser 與 IDepartment (此為 AbstractProductA 與 AbstractProductB)
2011-5-18 上午 12-43-32

實現各產品
2011-5-18 上午 12-44-44
2011-5-18 上午 12-45-34 

抽象工廠與各工廠的實現
2011-5-18 下午 11-05-52

客戶端程式碼
2011-5-18 下午 11-07-18

結果
2011-5-18 下午 11-08-11

=================================================================================================
根據以上,體驗出以下狀況

優點:
我們封裝 (new)。
第一:我們無法防止需求的更改,那我們希望讓改動變得最小,如果要更改資料庫存取,只需要更改具體工廠就可以做到。
第二:讓具體建立實體過程與用戶端分離,用戶端都是透過它們的抽象介面操縱實體,無須知道是 SQL Server 或是 Access 。

缺點:
當我們需要加入一個資料表,比方說 (Project),就必須撰寫 IProject、SqlserverProgject、AccessProject,還需要更改
IFactory、SqlserveerFactory、AccessFactory 才可以實現。


改進一:
於是我們使用「簡單工廠」來改進工廠類別,使用 DataAccess  類別。
2011-5-18 上午 12-48-59

Client 端,程式碼
2011-5-18 上午 12-52-00

結果
2011-5-18 上午 12-52-40 

===============================================================================================
改進一,讓我們的客戶端程式碼不在受改動資料庫的影響了,只是,若增加一個 Oracle 資料庫存取,現在反而
需要在 DataAccess 類別中的每個方法加入 switch case 來判別。

改進二:使用「反射原理」,讓物件的實體化由編譯時轉為執行時。
2011-5-18 下午 11-30-38

是的到目前為止,似乎有看到一絲絲的物件導向,客戶端與資料庫實作分開,若增加 Project 產品時,也只需要增加三個與
Project 相關的類別,再修改 DataAccess 增加一個靜態方法取得 IProject 接口;只是有點小遺憾,似乎更換當前欲使用的
資料庫存取時,還是要進去改程式(改 db  這個字串的值) 重新編譯。

=================================================================================================

改進三:用反射 + 設定檔實現資料存取程式。
加入 App.config 檔
2011-5-18 下午 11-40-15

再次調整 DataAccess 類別
2011-5-18 下午 11-42-14

結果
2011-5-18 下午 11-43-24

最後有一種東西叫做「依賴注入」 (Dependency Injection),也可以幫助我們處理「實體化」的動作,
可參考 In91Face BugPete.NET黃忠成

Reference

0 Comments:

張貼留言