在做這周設(shè)計模式的作業(yè)時對實現(xiàn)“FileSplitter支持多種文件分割算法”應(yīng)該模板方法模式還是策略模式糾結(jié)一下,通過對查閱相關(guān)資料得到了解答,遂記錄于此。
作業(yè)題目[1]:
考慮一個文件分割器的設(shè)計。MainForm為界面類,收集用戶輸入的文件路徑和分割數(shù)量。FileSpliter為實現(xiàn)文件分割的類型,其中Split()實現(xiàn)文件分割算法。1.要求為Split()支持多種文件分割算法(至少三種),在MainForm中靈活切換多種算法。2.在Split()分割過程中,實現(xiàn)對進度條的實時通知,即對ProgressBar賦值。3.使用松耦合面向?qū)ο笤O(shè)計方法和思想,無需編寫具體算法實現(xiàn),可使用偽碼表示設(shè)計。
在實現(xiàn)Split的過程,發(fā)現(xiàn)模板方法和策略模式都可以滿足題目的要求。模板方法以FileSplitter為基類,在Split實現(xiàn)文件分割的大流程和對進度條的實時通知,將真正實現(xiàn)切割的代碼doSplit聲明為保護方法,讓子類覆蓋。子類通過覆蓋父類的doSplit來實現(xiàn)算法定制。為達到在MainForm自由切換算法的目的,可以使用簡單工廠模式來自由生產(chǎn)FileSplitter實例。類結(jié)構(gòu)圖如下:

同樣該問題也可以使用策略模式來解決。策略模式首先聲明一個ISplitStragy接口,該方法包含了一個實現(xiàn)算法分割的接口doSplit。各個文件分割策略都實現(xiàn)ISplitStragy接口,然后FileSplitter包含一個ISplitStragy對象并在Split()函數(shù)中調(diào)用該策略。同樣,為了實現(xiàn)在MainForm中自由的切換算法,可以使用簡單工廠模式來自由生產(chǎn)FileSplitter實例。類結(jié)構(gòu)圖如下:

通過上述的講解,我們發(fā)現(xiàn)該題完全可以通過模板方法/策略模式來實現(xiàn),而且也看不出誰優(yōu)誰劣。那么這兩種方法是否等同了嗎?顯然不是。
首先,我們來看下這兩種模式的意圖。
策略模式[2]
定義一系列的算法,把它們一個個封裝起來, 使它們可相互替換。本模式使得算法可獨
立于使用它的客戶而變化。
模板方法[2]
定義一個操作中的算法的骨架,而將一些步驟延遲到子類中。TemplateMethod使得子類可以不改變一個算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。
從意圖上來看,兩者都在試圖解決算法多樣性對代碼結(jié)構(gòu)的沖擊。只是,策略模式通過將算法封裝成類,通過組合使用這些類。而模式方法則將算法的可變部分封裝成Hook,由子類定制。
從定義上來看,模式方法更加側(cè)重于業(yè)務(wù)流程相對復(fù)雜且穩(wěn)定,而其中的某些步驟(局部變化)變化相對劇烈的場景。而策略模式則是偏重于算法本身(整個算法)就變化相對距離的情形。因此,當使用場景中業(yè)務(wù)流程相對簡單且穩(wěn)定的情況,使用策略模式和模板方法都是可以得,但是更推薦用模板方法(模板方法更靈活)。
綜上:模板方法和策略模式都是解決算法多樣性對代碼結(jié)構(gòu)沖擊的問題。模板方法使用與業(yè)務(wù)場景相對復(fù)雜且穩(wěn)定的情況,策略模式使用與算法相對多樣靈活的場景。當業(yè)務(wù)相對簡單時,策略模式和模板方法幾乎等效,但是推薦使用策略模式。
參考資料:
[1]設(shè)計模式第一周作業(yè) http://mooc.study.163.com/learn/GeekBand-1000113005?tid=2001225007#/learn/hw?id=2001449004
[2]設(shè)計模式 GoF