模板模式和策略模式的區別

轉自:http://m.blog.csdn.net/article/details?id=7164227

模板模式和策略模式的區別


根據《深入淺出設計模式(C#/Java)》所述,


Strategy
模式的應用場景是:
1.
多個類的分別只是在於行爲不同
2.
你需要對行爲的算法做很多變動
3.
客戶不知道算法要使用的數據

 

Template Method模式的應用場景是:
1.
你想將相同的算法放在一個類中,將算法變化的部分放在子類中實現
2.
子類公共的算法應該放在一個公共的類中,避免代碼重複

 

仔細體會作者所提出的這幾個應用場景,你會發現它們其實沒什麼區別,StrategyTemplate Method模式都能完成要求.換句話說,作者沒抓住這兩個模式區別的"痛處"來給予詳細講解.下面我們再換個出發點來看看這兩種設計模式.

 

我們知道,設計模式中有這麼一個原則: Prefer composition to inheritance.這句話的背景是OO初期大家都把繼承看作是萬能的,並過度使用繼承來實現多態->可擴展.理解原則的時候不能脫離它的背景,不然就成盲從了.TemplateMethod模式應該是伴隨着OO的出現而萌生的.它是OO中最直觀的思考方式的結果.基類留下可變化的空間給子類,由繼承類來決定具體行爲.聽起來是不錯,不過...一旦基類的接口發生了變化,每個繼承類都得跟着修改才能夠繼續使用.這就是所謂高耦合與難維護的說法的來源.

 

StrategyTemplateMethod模式算是compositioninheritance的典型應用了,如果它們真的在功能上能完全互換,那何必要後者呢,全部都用前者不是很好麼? 再怎麼說,一個傾向於加深類層次結構的設計通常會使設計變得複雜,令後期維護變得困難.

Whendeciding between inheritance and composition, ask if you need to upcast to thebase type. If not, prefer composition (member objects) to inheritance. This caneliminate the perceived need for multiple base types.

Whichshould I prefer: composition or private inheritance? Use composition when youcan, private inheritance when you have to.

有一個說法總結得不錯: 到底該傾向於composition還是inheritance,決定於"變化的是什麼".如果基類的接口變化得很頻繁,那麼使用inheritance絕對是個噩夢;如果只是給基類新增方法,那麼堅持使用composition的話就得新增很多個delegate.

這麼說來,StrategyTemplate Method模式之間的區別,也是在"變化的是什麼"這個問題上了.

 

注意到,Strategy模式中,爲了讓Context類能夠調用,Strategy接口裏聲明的方法一般是公有的.TemplateMethod模式則不然,基類中留下的虛方法並不一定要是公有的,只要保證對繼承類可見就行.也就是說,TemplateMethod模式允許編寫庫的人採取更緊的訪問限制,Strategy模式則很難做到相同等級的限制.假如使用者獲得了一個Strategy接口的實現類的實例,他並不一定要將這個實例放入"原本應有"的那個Context,而可以隨意使用其中的接口方法.TemplateMethod模式可以利用protected的訪問權限,犧牲一點面向對象的封裝性,給自己的繼承類一定的訪問特權,來把一些訪問限制在"體系內",從而限制了外部對內的訪問.這仍然只是表象,不過我們已經接近問題的本質了.

 

這帶來的區別是什麼呢? Strategy模式允許外界使用其接口方法,因而可以將這個接口方法認爲是"一整個算法";TemplateMethod模式可以限制所留下的虛方法只對其繼承類可見,外部使用者不一定能夠直接使用這些虛方法,因而可以將這些虛方法認爲是"一個算法的一部分".GoF的設計模式那本書裏有這麼一句話:"Template methods use inheritance tovary part of an algorithm. Strategies use delegation to vary the entirealgorithm.",說的正是這個問題.回到具體問題上,如果我們要封裝的算法適合於提供給用戶任意使用,"一整個算法",那麼用Strategy模式較好;如果要封裝的變化是一個算法中的部分(換言之,大算法的步驟是固定的),而且我們不希望用戶直接使用這些方法,那麼應該使用Template Method模式.就此,問題的"痛處"算是抓住了.

 

回到書中的例子.爲什麼使用Template Method模式比較好呢? 我覺得是因爲那個format()方法並不應該被用戶直接單獨調用,因而用protected限制住了對它的訪問.這就不適合Strategy模式了(Strategy意味着默認用戶單獨去使用算法).

但是話說回來,作者提到了Singleton.要是用了TemplateMethod,Singleton基本上就泡湯了.但是又沒有源代碼看看作者到底實現出來的是什麼樣的,無法猜透他的想法啊.

 

爲了這麼一個問題,我硬是跟axx大爭了一個晚上...我總是覺得StrategyTemplateMethod模式在使用中沒什麼區別,而根據Prefer composition to inheritance原則,Strategy模式相對更合適於較多的場景.axx大則不停重複兩種模式帶來的訪問限制不一樣,但一直沒能表述得讓我明白.幸好axx大脾氣好,不然這麼爭一次還真傷元氣

 

其中評論:

dave_xiang

博主更多是從技術層面看的問題,我覺得你文章最開頭提出的觀點更多的是從OO本身來看的,因爲面向對象的出現的目的是想以一種比較貼近現實世界的方法去編程(讓軟件工程師更好理解),是一種開放的編程方法。
如果我們把一個類看成一個對象,那麼文章開頭給出的區別就比較好理解了。個人覺得這不是可不可以實現的問題,而是模式本身的優勢的問題,它適應用某一種場景,那麼就可以發揮其優勢。至於文中提到的不同訪問權限,個人覺得一般情況可以不必太在意,因爲開發工作是一個被組織有序的過程,過程中的代碼間的結構是相對固定,不能因爲某一個類開放了方法,就去調用。一切應該是以實現業務功能和保持代碼結構良好性爲主。

 



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章