工廠三兄弟之工廠方法模式(一)

2021-08-09 06:11:49 字數 1508 閱讀 3834

簡單工廠模式雖然簡單,但存在乙個很嚴重的問題。當系統中需要引入新產品時,由於靜態工廠方法通過所傳入引數的不同來建立不同的產品,這必定要修改工廠類的源**,將違背「開閉原則」,如何實現增加新產品而不影響已有**?

工廠方法模式應運而生,本文將介紹第二種工廠模式——工廠方法模式。

1 日誌記錄器的設計

sunny軟體公司欲開發乙個系統執行日誌記錄器(logger),該記錄器可以通過多種途徑儲存系統的執行日誌,如通過檔案記錄或資料庫記錄,使用者可以通過修改配置檔案靈活地更換日誌記錄方式。在設計各類日誌記錄器時,sunny公司的開發人員發現需要對日誌記錄器進行一些初始化工作,初始化引數的設定過程較為複雜,而且某些引數的設定有嚴格的先後次序,否則可能會發生記錄失敗。如何封裝記錄器的初始化過程並保證多種記錄器切換的靈活性是sunny公司開發人員面臨的乙個難題。

sunny

公司的開發人員通過對該需求進行分析,發現該日誌記錄器有兩個設計要點:

(1) 需要封裝日誌記錄器的初始化過程,這些初始化工作較為複雜,例如需要初始化其他相關的類,還有可能需要讀取配置檔案(例如連線資料庫或建立檔案),導致**較長,如果將它們都寫在建構函式中,會導致建構函式龐大,不利於**的修改和維護;

(2) 使用者可能需要更換日誌記錄方式,在客戶端**中需要提供一種靈活的方式來選擇日誌記錄器,盡量在不修改源**的基礎上更換或者增加日誌記錄方式。

sunny公司開發人員最初使用簡單工廠模式對日誌記錄器進行了設計,初始結構如圖1所示:

圖1 基於簡單工廠模式設計的日誌記錄器結構圖

在圖1中,logge***ctory充當建立日誌記錄器的工廠,提供了工廠方法createlogger()用於建立日誌記錄器,logger是抽象日誌記錄器介面,其子類為具體日誌記錄器。其中,工廠類logge***ctory**片段如下所示:

//日誌記錄器工廠  

class logge***ctory

else if(args.equalsignorecase("file"))

else

} }

為了突出設計重點,我們對上述**進行了簡化,省略了具體日誌記錄器類的初始化**。在logge***ctory類中提供了靜態工廠方法createlogger(),用於根據所傳入的引數建立各種不同型別的日誌記錄器。通過使用簡單工廠模式,我們將日誌記錄器物件的建立和使用分離,客戶端只需使用由工廠類建立的日誌記錄器物件即可,無須關心物件的建立過程,但是我們發現,雖然簡單工廠模式實現了物件的建立和使用分離,但是仍然存在如下兩個問題:

(1) 工廠類過於龐大,包含了大量的if…else…**,導致維護和測試難度增大;

(2) 系統擴充套件不靈活,如果增加新型別的日誌記錄器,必須修改靜態工廠方法的業務邏輯,違反了「開閉原則」。

如何解決這兩個問題,提供一種簡單工廠模式的改進方案?這就是本文所介紹的工廠方法模式的動機之一。

工廠三兄弟之工廠方法模式(四)

sunny公司開發人員通過進一步分析,發現可以通過多種方式來初始化日誌記錄器,例如可以為各種日誌記錄器提供預設實現 還可以為資料庫日誌記錄器提供資料庫連線字串,為檔案日誌記錄器提供檔案路徑 也可以將引數封裝在乙個object型別的物件中,通過object物件將配置引數傳入工廠類。此時,可以提供一組過...

工廠三兄弟之工廠方法模式(二)

2 工廠方法模式概述 在簡單工廠模式中只提供乙個工廠類,該工廠類處於對產品類進行例項化的中心位置,它需要知道每乙個產品物件的建立細節,並決定何時例項化哪乙個產品類。簡單工廠模式最大的缺點是當有新產品要加入到系統中時,必須修改工廠類,需要在其中加入必要的業務邏輯,這違背了 開閉原則 此外,在簡單工廠模...

工廠三兄弟之工廠方法模式(四)

sunny公司開發人員通過進一步分析,發現可以通過多種方式來初始化日誌記錄器,例如可以為各種日誌記錄器提供預設實現 還可以為資料庫日誌記錄器提供資料庫連線字串,為檔案日誌記錄器提供檔案路徑 也可以將引數封裝在乙個object型別的物件中,通過object物件將配置引數傳入工廠類。此時,可以提供一組過...