類圖
為什么要將飛行和呱呱叫行為算法提取出來?
這些行為是容易變化的,將它們提取出來后續(xù)行為的具體實(shí)現(xiàn)方式發(fā)生變化不會(huì)對(duì)duck類產(chǎn)生任何影響,只需要修改具體行為實(shí)現(xiàn)類自身的邏輯。(即為封裝變化)
很多鴨子類型其實(shí)并不需要飛行,如橡皮鴨,死鴨子等,如果將飛行和叫行為放在duck父類中,所有的duck實(shí)現(xiàn)類都必須實(shí)現(xiàn)該方法,不需要該方法行為的鴨子在實(shí)現(xiàn)時(shí)就只能override該方法后空著不實(shí)現(xiàn)具體邏輯,這樣會(huì)導(dǎo)致產(chǎn)生很多重復(fù)無用代碼。將這兩種行為作為duck的類變量,所有的飛行和呱呱叫都會(huì)委托具體行為去執(zhí)行,則可以清除這些無用代碼。(個(gè)人另外看法,對(duì)于無用代碼來說,可以把fly和quack方法座位duck類的普通方法,不要定義為抽象方法就可以了,不需要實(shí)現(xiàn)該方法的鴨子不要重寫該方法就好了)(組合代替繼承)
<b>個(gè)人看來最最最重要的一點(diǎn),也是策略模式的核心功能:運(yùn)行時(shí)可動(dòng)態(tài)改變行為策略</b>,通過duck類暴露setter方法的方式,調(diào)用方可隨時(shí)根據(jù)需求更換duck類的行為策略,這也是在我看來<b>策略模式跟模版方法模式最大最大的區(qū)別</b>
策略模式在實(shí)際開發(fā)中的應(yīng)用
首先,我在百度上搜到了好多展示自己如何運(yùn)用策略模式重構(gòu)自己代碼的例子,看完都發(fā)現(xiàn)其實(shí)完全不是那么回事,大多數(shù)案例都是以if else或者switch case這種代碼為切入點(diǎn),說根據(jù)策略模式可以去掉這些難看的層層判斷,他們基本采用的方式是維護(hù)了一個(gè)map,客戶端調(diào)用時(shí)通過map找到對(duì)應(yīng)的策略,然后執(zhí)行策略方法....從本質(zhì)上看這和if else沒有任何本質(zhì)的區(qū)別吧,只是把判斷具體用哪個(gè)策略的方法從if else改善成用map查找了而已。
個(gè)人覺得策略模式要想用好,必須反映出運(yùn)行時(shí)動(dòng)態(tài)改變策略的能力。不然即使使用了策略模式,也就是模版方法模式的變種而已!!!
另外,關(guān)于運(yùn)行時(shí)動(dòng)態(tài)改變策略,應(yīng)該是每一次改變是全局性的改變,只要改變了之后這個(gè)context類在下一次被修改策略前都要保持以現(xiàn)在的策略響應(yīng)請(qǐng)求。(就是說改變不是臨時(shí)改變,。。。不知道怎么形容)
在非單機(jī)的環(huán)境中,策略模式可能需要依靠消息中間件同步各服務(wù)器同時(shí)響應(yīng)策略修改,在分布式web開發(fā)中,策略模式使用場(chǎng)景目前我狹隘的眼光看來還比較難用上,稍微可以想到的可能是一些容災(zāi)方案上面的,全局的策略變更也必須通過消息中間件或者分布式數(shù)據(jù)庫(kù)緩存等來實(shí)現(xiàn),且要考慮一些容災(zāi)邏輯。
下面是自己想到的一些可以運(yùn)營(yíng)策略模式的場(chǎng)景:
- head first中提到的游戲中更換游戲角色的武器
- 實(shí)時(shí)翻譯程序中點(diǎn)擊切換語(yǔ)言按鈕時(shí)更換翻譯策略