在面向對象的程序設計中,某一功能的實現往往是依賴多個類的協同工作,這當中不必可避免的會有一個核心的關鍵類,非關鍵類對關鍵類的依賴程度比較高(耦合比較緊),關鍵類的變動會景響到非關鍵類與其通信。比如在某個MIS系統中,用戶數據是存儲在文件中的,那麼所有數據的讀取與保存都依賴與那和與文件進行通信的類。突然某一天客戶說要將數據存儲到數據庫中,那麼我們是必要找出所有使用這些與文件通信的類的代碼,並使用新寫的與數據庫通信的類將其替換掉。這個改動量是可想而知的。那麼有沒有一種好的設計模式能夠降低這種情況下的代碼改動量呢?
答案是肯定的。使用工廠模式。我們可以定義一個工廠類,提供一系列的創造對象的方法,代替類似TObject.Create的代碼,降低類與類之間的耦合。
我們就以前面講到的情況為例,來說明工廠模式的使用。在系統中我們已經定義了一個負責數據讀取的抽像類TDataReader和負責數據保存的抽象類TDataWriter,並分別派生了文件讀取類TFileDataReader和文件保存類TFileDataWriter。
//此處僅為說明,其他定義省略
type
TDataReader = class
private
.......
protected
.......
public
.......
procedure Read; virtual; abstract;
.......
end;
TDataWriter = class
private
.......
protected
.......
public
.......
procedure Write; virtual; abstract;
.......
end;
TFileDataReader = class(TDataReader)
private
.......
protected
.......
public
.......
procedure Read; override;
.......
end;
TFileDataWriter = class(TDataWriter)
private
.......
protected
.......
public .......
procedure Write; override;
.......
end;
在重構這前,凡是用到數據讀取與保存的地方,都是使用類似下面的代碼
var
Reader: TFileDataReader;
begin
......
Reader := TFileDataReader.Create;
Reader.Read;
......
end;
var
Writer: TFileDataWriter;
begin
......
Writer := TFileDataWriter.Create; Writer.Write;
......
end;
現在客戶要求我們將所有的數據存儲到數據庫中,就意味著我們要再分別從TDataReader類和TDataWriter類派生出兩個與數據庫通信的類TDBDataReader和TDBDataWriter(之前良好的類繼承設計使我們在此省下了許多修工作),然後將類似上面的的Reader和Writer的構建語句改為
Reader := TDBDataReader.Crette;
Writer := TDBDataWriter.Create;
這樣的改動也能達到客戶的要求,但我們誰也不能保證在此之後不會再有任何的變化,為了不讓噩夢重演,我們決定不使用這種修改方式。而是定義一個工廠類,負責創建出我們需要的數據讀取類和保存類,即使將來再有變化,我們的修改也僅限於在工廠類內部的改動。
Type
TDataReaderFactory = class
public
function CreatReader: TDataReader;
end;
TDataWriterFactory = class
public
function CreateWriter: TDataWriter;
end;
implementation
...{ TDataReaderFactory }
function TDataReaderFactory.CreatReader: TDataReader;
begin
Result := TDBDataReader.Create;
end;
...{ TDataWriterFactory }
function TDataWriterFactory.CreateWriter: TDataWriter;
begin
Result := TDBDataWriter.Create;
end;
在使用到數據讀寫類的地方,將代碼改為
Reader := TDataReaderFactory.CretteReader;
Writer := TDataWriterFactory.CreateWriter;
至此,我們就通過工廠模式實現了客戶端代碼與數據存取類的松散耦合,也為將來的再修改提供了靈活性。