摘要:可以使用其他模式來修正這個缺陷,如工廠方法模式代理模式或享元模式。我們的策略模式只是實現(xiàn)了策略的管理,但是沒有嚴格地定義適當(dāng)?shù)膱鼍笆褂眠m當(dāng)?shù)牟呗裕趯嶋H項目中,一般通過工廠方法模式來實現(xiàn)策略類的聲明。源碼地址參考文獻設(shè)計模式之禪
定義
Define a family of algorithms,encapsulate each one,and make them interchangeable.定義一組算法,將每個算法都封裝起來,并且使它們之間可以互換。
策略模式使用的就是面向?qū)ο蟮睦^承和多態(tài)機制,非常容易理解和掌握
實現(xiàn) 抽象策略策略、算法家族的抽象,通常為接口,也可以是抽象類,定義每個策略或算法必須具有的方法和屬性。
public interface Strategy { /** * 策略模式的運算法則 */ void doSomething(); }具體策略
實現(xiàn)抽象策略中的操作,該類含有具體的算法
public class ConcreteStrategyA implements Strategy { @Override public void doSomething() { System.out.println("具體策略A的運算法則"); } }
public class ConcreteStrategyB implements Strategy { @Override public void doSomething() { System.out.println("具體策略B的運算法則"); } }封裝類
也叫做上下文類或環(huán)境類,起承上啟下封裝作用,屏蔽高層模塊對策略、算法的直接訪問,封裝可能存在的變化。
策略模式的重點就是封裝角色,它是借用了代理模式的思路,和代理模式的差別就是策略模式的封裝角色和被封裝的策略類不用是同一個接口,如果是同一個接口那就成為了代理模式。
public class Context { /** * 抽象策略 */ private Strategy strategy; /** * 構(gòu)造函數(shù)設(shè)置具體策略 * * @param strategy */ public Context(Strategy strategy) { this.strategy = strategy; } /** * 封裝后的策略方法 */ public void executeStrategy() { this.strategy.doSomething(); } }客戶端代碼
public class Client { public static void main(String[] args) { // 聲明一個具體的策略 Strategy strategyA = new ConcreteStrategyA(); // 聲明上下文對象 Context contextA = new Context(strategyA); // 執(zhí)行封裝后的方法 contextA.executeStrategy(); Strategy strategyB = new ConcreteStrategyB(); Context contextB = new Context(strategyB); contextB.executeStrategy(); } }優(yōu)點
算法可以自由切換
這是策略模式本身定義的,只要實現(xiàn)抽象策略,它就成為策略家族的一個成員,通過封裝角色對其進行封裝,保證對外提供“可自由切換”的策略。
避免使用多重條件判斷
如果沒有策略模式,一個策略家族有5個策略算法,一會要使用A策略,一會要使用B策略,怎么設(shè)計呢?使用多重的條件語句?多重條件語句不易維護,而且出錯的概率大大增強。使用策略模式后,可以由其他模塊決定采用何種策略,策略家族對外提供的訪問接口就是封裝類,簡化了操作,同時避免了條件語句判斷。
擴展性良好
在現(xiàn)有的系統(tǒng)中增加一個策略太容易了,只要實現(xiàn)接口就可以了,其他都不用修改,類似于一個可反復(fù)拆卸的插件,這大大地符合了OCP原則。
缺點策略類數(shù)量增多
每一個策略都是一個類,復(fù)用的可能性很小,類數(shù)量增多。
所有的策略類都需要對外暴露
上層模塊必須知道有哪些策略,然后才能決定使用哪一個策略,這與迪米特法則是相違背的(只是想使用一個策略,卻要要了解這個策略)。可以使用其他模式來修正這個缺陷,如工廠方法模式、代理模式或享元模式。
使用場景多個類只有在算法或行為上稍有不同的場景。
算法需要自由切換的場景。
例如,算法的選擇是由使用者決定的,或者算法始終在進化,特別是一些站在技術(shù)前沿的行業(yè),連業(yè)務(wù)專家都無法給你保證這樣的系統(tǒng)規(guī)則能夠存在多長時間,在這種情況下策略模式是你最好的助手。
需要屏蔽算法規(guī)則的場景。
現(xiàn)在的科技發(fā)展得很快,人腦的記憶是有限的(就目前來說是有限的),太多的算法你只要知道一個名字就可以了,傳遞相關(guān)的數(shù)字進來,反饋一個運算結(jié)果,萬事大吉。
注意事項如果系統(tǒng)中的一個策略家族的具體策略數(shù)量超過4個,則需要考慮使用混合模式,解決策略類膨脹和對外暴露的問題,否則日后的系統(tǒng)維護就會成為一個燙手山芋,誰都不想接。最佳實踐
策略模式是一個非常簡單的模式(主要是用了Java繼承與多態(tài)的機制)。它在項目中使用得非常多,但多帶帶使用的地方就比較少了,因為它有致命缺陷:所有的策略都需要暴露出去,這樣才方便客戶端決定使用哪一個策略。我們的策略模式只是實現(xiàn)了策略的管理,但是沒有嚴格地定義“適當(dāng)?shù)膱鼍啊笔褂谩斑m當(dāng)?shù)牟呗浴保趯嶋H項目中,一般通過工廠方法模式來實現(xiàn)策略類的聲明。
擴展(策略枚舉)它是一個枚舉。
它是一個濃縮了的策略模式的枚舉。
啥意思?來看代碼:
public enum Calculator { PLUS("+") { public int exec(int x, int y) { return x + y; } }, MINUS("-") { public int exec(int x, int y) { return x - y; } }; private final String symbol; Calculator(String symbol) { this.symbol = symbol; } public String getSymbol() { return this.symbol; } /** * 聲明一個抽象方法 * 枚舉類型中的抽象方法必須被它的所有常量中的具體方法所覆蓋(被稱為特定于常量的方法實現(xiàn)) */ public abstract int exec(int a, int b); }
把原有定義在抽象策略中的方法移植到枚舉中,每個枚舉成員就成為一個具體策略
public class Client { public static void main(String[] args) { int x = 100; int y = 10; System.out.println(x + " + " + y + " = " + Calculator.PLUS.exec(x, y)); System.out.println(x + " - " + y + " = " + Calculator.MINUS.exec(x, y)); } }
代碼量非常少,而且還有一個顯著的優(yōu)點:真實地面向?qū)ο?/p>
Calculator.PLUS.exec(x, y)類似于“拿出計算器(Calculator),對x和y進行加法運算(MINUS),并立刻執(zhí)行(exec)”,這與我們?nèi)粘=佑|邏輯非常相似
策略枚舉是一個非常優(yōu)秀和方便的模式(《Effective Java》中枚舉相關(guān)條目也有詳細介紹該模式),但是它受枚舉類型的限制,每個枚舉項都是public、final、static的,擴展性受到了一定的約束,因此在系統(tǒng)開發(fā)中,策略枚舉一般擔(dān)當(dāng)不經(jīng)常發(fā)生變化的角色。
源碼地址:https://gitee.com/tianranll/j...
參考文獻:《設(shè)計模式之禪》、《Effective Java》
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/75082.html
摘要:今天我們來學(xué)習(xí)一種行為型模式,策略模式。策略模式讓算法獨立于使用它的客戶而變化,也稱為政策模式。策略模式提供了可以替換繼承關(guān)系的辦法。使用策略模式可以避免使用多重條件轉(zhuǎn)移語句。策略模式將造成產(chǎn)生很多策略類。今天我們來學(xué)習(xí)一種行為型模式,策略模式(Strategy Pattern)。模式定義定義一系列算法,將每一個算法封裝起來,并讓它們可以相互替換。策略模式讓算法獨立于使用它的客戶而變化,也稱...
摘要:孫臏心里一萬個草泥馬在奔騰,差點沒噎死自己滾一邊去,我們這盤跟他賽馬開始,策略模式上場。在設(shè)計模式之禪中的提出通過策略枚舉和反射機制對策略模式進行改良,膜拜了但是要添加或淘汰策略,還是得去對枚舉進行修改,也不符合開閉原則。 今天給大家說說田忌賽馬的故事。如有雷同,純屬巧合!話說在戰(zhàn)國時期,群雄割據(jù),硝煙四起,茶余飯后還是少不了娛樂活動的,其中賽馬是最火爆的。一天,孫臏看到田忌像個死雞似...
摘要:注解方式優(yōu)點使用注解方式可以極大的減少使用模版方法模式帶來的擴展時需要繼承模版類的弊端,工廠注解的方式可以無需關(guān)心其他業(yè)務(wù)類的實現(xiàn),而且減少了類膨脹的風(fēng)險。 在上一篇文章Java設(shè)計模式綜合運用(門面+模版方法+責(zé)任鏈+策略)中,筆者寫了一篇門面模式、模版方法、責(zé)任鏈跟策略模式的綜合運用的事例文章,但是后來筆者發(fā)現(xiàn),在實現(xiàn)策略模式的實現(xiàn)上,發(fā)現(xiàn)了一個弊端:那就是如果在后續(xù)業(yè)務(wù)發(fā)展中,需...
閱讀 3440·2021-10-14 09:42
閱讀 2729·2021-09-08 10:44
閱讀 1304·2021-09-02 10:18
閱讀 3609·2021-08-30 09:43
閱讀 2799·2021-07-29 13:49
閱讀 3725·2019-08-29 17:02
閱讀 1581·2019-08-29 15:09
閱讀 1038·2019-08-29 11:01