中國住房和城鄉(xiāng)建設(shè)部網(wǎng)站安全seo優(yōu)化排名軟件
策略模式是一種行為設(shè)計(jì)模式,就是定義一系列算法,然后將每一個算法封裝起來,并使它們可相互替換。本模式通過定義一組可相互替換的算法,實(shí)現(xiàn)將算法獨(dú)立于使用它的用戶而變化。
Strategy is a behavioral design pattern that defines a series of algorithms, then encapsulates each algorithm and
makes them interchangeable. This pattern enables algorithms to vary independently of the users who use them by
defining a set of interchangeable algorithms.
結(jié)構(gòu)設(shè)計(jì)
為實(shí)現(xiàn)一系列可相互替換的算法,可定義一個公共接口,然后定義一組實(shí)現(xiàn)該接口的具體策略,這樣就可在上下文中使用該接口調(diào)用具體策略上定義的算法。
Context,上下文,維護(hù)指向具體策略的引用,且僅通過策略接口與該對象進(jìn)行交流。上下文,可以維護(hù)一個對策略對象的引用,這符合組合設(shè)計(jì)原則。
上下文,定義了一個接口以封裝對策略對象的訪問。如果策略對象直接暴露給外部使用,會導(dǎo)致其內(nèi)部實(shí)現(xiàn)細(xì)節(jié)的暴露,從而增加接口使用難度。
Strategy,策略基類或策略接口,聲明了一個上下文用于執(zhí)行策略的方法。
ConcreteStrategy,具體策略類,實(shí)現(xiàn)了策略類聲明的方法。
策略模式類圖表示如下:
偽代碼實(shí)現(xiàn)
接下來將使用代碼介紹下策略模式的實(shí)現(xiàn)。
// 1、抽象策略類,聲明執(zhí)行策略的方法
public interface IStrategy {void operation(String paramStr);
}
// 2、具體策略類A,實(shí)現(xiàn)策略接口聲明的方法
public class ConcreteAStrategy implements IStrategy {@Overridepublic void operation(String paramStr) {System.out.println("do some thing in the concrete A instance");}
}
// 2、具體策略類B,實(shí)現(xiàn)策略接口聲明的方法
public class ConcreteBStrategy implements IStrategy {@Overridepublic void operation(String paramStr) {System.out.println("do some thing in the concrete B instance");}
}
// 3、策略上下文,維護(hù)指向具體策略的引用,且僅通過策略接口與該對象進(jìn)行交流。這里提供兩種使用策略類的方式。
public class StrategyContext {private static final Map<String, IStrategy> STRATEGY_MAP;private IStrategy strategy;static {STRATEGY_MAP = new HashMap<>();STRATEGY_MAP.put("type A", new ConcreteAStrategy());STRATEGY_MAP.put("type B", new ConcreteBStrategy());}public StrategyContext() {}public StrategyContext(IStrategy strategy) {this.strategy = strategy;}public void doSomething(String paramStr) {strategy.operation(paramStr);}public void doSomething(String strategyType, String paramStr) {IStrategy currentStrategy = STRATEGY_MAP.get(strategyType);if (Objects.isNull(currentStrategy)) {throw new RuntimeException("strategy is null");}currentStrategy.operation(paramStr);}
}
// 4、策略模式客戶端
public class StrategyClient {public void test() {StrategyContext strategyContextA = new StrategyContext(new ConcreteAStrategy());strategyContextA.doSomething("TEST");StrategyContext strategyContextB = new StrategyContext();strategyContextB.doSomething("type B", "TEST");}
}
適用場景
在以下情況下可以考慮使用策略模式:
(1) 如果在一個系統(tǒng)里面有許多類,它們之間的區(qū)別僅在于它們的行為,那么使用策略模式可以動態(tài)地讓一個對象在許多行為中選擇一種行為。
(2) 一個系統(tǒng)需要動態(tài)地在幾種算法中選擇一種, 可考慮使用策略模式。
策略模式能夠?qū)ο箨P(guān)聯(lián)至可以不同方式執(zhí)行特定子任務(wù)的不同子對象,從而以間接方式在運(yùn)行時更改對象行為。
(3) 當(dāng)類中使用了復(fù)雜條件運(yùn)算符(如多重的條件選擇語句)以在同一算法的不同變體中切換時, 可使用該模式。
策略模式可將所有繼承自同樣接口的算法抽取到獨(dú)立類中,因此可以不需要條件語句。原始對象并不實(shí)現(xiàn)所有算法的變體,而是將執(zhí)行工作委派給其中的一個獨(dú)立算法對象。
(4) 不希望客戶端知道復(fù)雜的、與算法相關(guān)的數(shù)據(jù)結(jié)構(gòu),在具體策略類中封裝算法和相關(guān)的數(shù)據(jù)結(jié)構(gòu),提高算法的保密性與安全性。
策略模式讓你能將各種算法的代碼、 內(nèi)部數(shù)據(jù)和依賴關(guān)系與其他代碼隔離開來。 不同客戶端可通過一個簡單接口執(zhí)行算法, 并能在運(yùn)行時進(jìn)行切換。
優(yōu)缺點(diǎn)
策略模式有以下優(yōu)點(diǎn):
(1) 符合開閉原則。可以在不修改原有系統(tǒng)的基礎(chǔ)上選擇算法或行為,也可以靈活地增加新的算法或行為。
(2) 定義一系列可重用的算法。策略模式提供了管理相關(guān)的算法族的辦法。
(3) 使用組合來代替繼承。實(shí)現(xiàn)支持多種算法或行為的方法。
(4) 避免使用多重條件語句。當(dāng)不同的行為堆砌在一個類時,很難避免使用條件語句來選擇合適的行為。如果將行為封裝在一個個獨(dú)立的Strategy類中,則可消除這些條件語句。
如使用字典的初始化從文件中讀取的方式,就可將策略配置移除到外部,從而進(jìn)一步減少不必要的代碼修改。
但是策略模式也存在以下缺點(diǎn):
(1) 如果使用的算法極少發(fā)生改變,那么沒有任何理由引入新的類和接口。使用策略模式只會讓程序過于復(fù)雜。
(2) 策略模式將造成產(chǎn)生很多策略類,可以通過使用享元模式在一定程度上減少對象的數(shù)量。
(3) 許多現(xiàn)代編程語言支持函數(shù)類型功能,允許在一組匿名函數(shù)中實(shí)現(xiàn)不同版本的算法。這樣,就可以使用這些函數(shù)來替換策略對象,無需借助額外的類和接口來保持代碼簡潔。如在Java語言中是Lambda表達(dá)式,在C++語言中是函數(shù)指針。
參考
《設(shè)計(jì)模式 可復(fù)用面向?qū)ο筌浖幕A(chǔ)》 Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides 著, 李英軍, 馬曉星等譯
https://design-patterns.readthedocs.io/zh_CN/latest/behavioral_patterns/strategy.html 策略模式
https://refactoringguru.cn/design-patterns/strategy 策略模式
https://www.runoob.com/design-pattern/strategy-pattern.html 策略模式
https://www.cnblogs.com/adamjwh/p/11011095.html 簡說設(shè)計(jì)模式——策略模式
https://blog.csdn.net/ShuSheng0007/article/details/88085445 秒懂設(shè)計(jì)模式之策略模式