簡介
策略模式:策略模式是一種行為型模式,它將對象和行為分開,將行為定義為 一個行為接口 和 具體行為的實現(xiàn)。策略模式最大的特點是行為的變化,行為之間可以相互替換,每個if判斷都可以理解為就是一個策略,本模式使得算法可獨立于使用它的用戶而變化。
結(jié)構(gòu)
策略模式包含如下角色:
Strategy:
抽象策略類:策略是一個接口,該接口定義若干個算法標(biāo)識,即定義了若干個抽象方法(如下圖的algorithm())
Context: 環(huán)境類 /上下文類:
上下文是依賴于接口的類(是面向策略設(shè)計的類,如下圖Context類),即上下文包含用策略(接口)聲明的變量(如下圖的strategy成員變量)。
上下文提供一個方法(如下圖Context類中的的lookAlgorithm()方法),持有一個策略類的引用,最終給客戶端調(diào)用。該方法委托策略變量調(diào)用具體策略所實現(xiàn)的策略接口中的方法(實現(xiàn)接口的類重寫策略(接口)中的方法,來完成具體功能)
ConcreteStrategy: 具體策略類:
具體策略是實現(xiàn)策略接口的類(如下圖的ConcreteStrategyA類和ConcreteStrategyB類)。具體策略實現(xiàn)策略接口所定義的抽象方法,即給出算法標(biāo)識的具體方法。(說白了就是重寫策略類的方法?。?/p>

代碼
接口類
public interface SeasonsStrategy {
/**
* 根據(jù)季節(jié)執(zhí)行不同方案
*
* @param seasons
* @return
*/
String execute(String seasons);
}
策略類
@Component("spring")
public class SpringStrategy implements SeasonsStrategy {
@Override
public String execute(String seasons) {
return seasons + "來了,我們一起去放風(fēng)箏吧";
}
}
@Component("summer")
public class SummerStrategy implements SeasonsStrategy {
@Override
public String execute(String seasons) {
return seasons + "來了,我們一起去游泳吧";
}
}
@Component("autumn")
public class AutumnStrategy implements SeasonsStrategy {
@Override
public String execute(String seasons) {
return seasons + "來了,我們一起去看楓葉吧";
}
}
@Component("winter")
public class WinterStrategy implements SeasonsStrategy {
@Override
public String execute(String seasons) {
return seasons + "來了,我們一起去堆雪人吧";
}
}
枚舉類
public enum SeasonsEnum {
SRPING(1, "spring", "春天"),
SUMMER(2, "summer", "夏天"),
AUTUMN(3, "autumn", "秋天"),
WINTER(4, "winter", "冬天");;
private int code;
private String en;
private String zh;
public int getCode() {
return code;
}
public String getEn() {
return en;
}
public String getZh() {
return zh;
}
SeasonsEnum(int code, String en, String zh) {
this.code = code;
this.en = en;
this.zh = zh;
}
public static SeasonsEnum getByCode(Integer code) {
return Arrays.stream(SeasonsEnum.values()).filter(a -> a.getCode() == code).findFirst().orElse(null);
}
}
工廠類
@Component
public class SeasonsFactory {
/**
* Spring會自動將strategy接口的實現(xiàn)類注入到這個map中,key為bean id ,value值則為對應(yīng)的策略實現(xiàn)類
*/
@Resource
private Map<String, SeasonsStrategy> strategy;
/**
* 統(tǒng)一入口
*
* @param seasons
* @return
*/
public String handle(SeasonsEnum seasons) {
SeasonsStrategy seasonsStrategy = strategy.get(seasons.getEn());
return seasonsStrategy.execute(seasons.getZh());
}
}
測試類
@RestController
@RequestMapping("/strategy")
public class StrategyController {
@Resource
private SeasonsFactory seasonsFactory;
@GetMapping("/{code}")
public String strategyTest(@PathVariable("code") Integer code) {
if (code == null) {
return "季節(jié)不能為空";
}
SeasonsEnum seasons = SeasonsEnum.getByCode(code);
if (seasons == null) {
return "季節(jié)異常";
}
return seasonsFactory.handle(seasons);
}
}
適用場景
- 如果在一個系統(tǒng)里面有許多類,它們之間的區(qū)別僅在于它們 的行為,那么使用策略模式可以動態(tài)地讓一個對象在許多行 為中選擇一種行為。
- 一個系統(tǒng)需要動態(tài)地在幾種算法中選擇一種。
- 如果一個對象有很多的行為,如果不用恰當(dāng)?shù)哪J?,這些行 為就只好使用多重的條件選擇語句來實現(xiàn)。
- 不希望客戶端知道復(fù)雜的、與算法相關(guān)的數(shù)據(jù)結(jié)構(gòu),在具體 策略類中封裝算法和相關(guān)的數(shù)據(jù)結(jié)構(gòu),提高算法的保密性與 安全性。
1、電商網(wǎng)站支付方式,一般分為銀聯(lián)、微信、支付寶,可以采用策略模式
2、電商網(wǎng)站活動方式,一般分為滿減送、限時折扣、包郵活動,拼團(tuán)等可以采用策略模式
注意事項和細(xì)節(jié)
策略模式的關(guān)鍵是:分析項目中變化部分與不變部分
策略模式的核心思想是:多用組合/聚合少用繼承;用行為類組合,而不是行為的繼承更有彈性
體現(xiàn)了“對修改關(guān)閉,對擴(kuò)展開放”原則,客戶端增加行為不用修改原有代碼,只 要添加一種策略(或者行為)即可,避免了使用多重轉(zhuǎn)移語句(if..else if..else)
提供了可以替換繼承關(guān)系的辦法: 策略模式將算法封裝在獨立的Strategy類中使得 你可以獨立于其Context改變它,使它易于切換、易于理解、易于擴(kuò)展
需要注意的是:每添加一個策略就要增加一個類,當(dāng)策略過多是會導(dǎo)致類數(shù)目龐大
總結(jié)
? 在策略模式中定義了一系列算法,將每一個算法封裝起來,并讓它們 可以相互替換。策略模式讓算法獨立于使用它的客戶而變化,也稱為 政策模式。策略模式是一種對象行為型模式。
? 策略模式包含三個角色:環(huán)境類在解決某個問題時可以采用多種策略,在環(huán)境類中維護(hù)一個對抽象策略類的引用實例;抽象策略類為所支持的算法聲明了抽象方法,是所有策略類的父類;具體策略類實現(xiàn)了在抽象策略類中定義的算法。
? 策略模式是對算法的封裝,它把算法的責(zé)任和算法本身分割開,委派 給不同的對象管理。策略模式通常把一個系列的算法封裝到一系列的 策略類里面,作為一個抽象策略類的子類。
? 策略模式主要優(yōu)點在于對“開閉原則”的完美支持,在不修改原有系 統(tǒng)的基礎(chǔ)上可以更換算法或者增加新的算法,它很好地管理算法族, 提高了代碼的復(fù)用性,是一種替換繼承,避免多重條件轉(zhuǎn)移語句的 實現(xiàn)方式;其缺點在于客戶端必須知道所有的策略類,并理解其區(qū)別,同時在一定程度上增加了系統(tǒng)中類的個數(shù),可能會存在很多策略類。
? 策略模式適用情況包括:在一個系統(tǒng)里面有許多類,它們之間的區(qū) 別僅在于它們的行為,使用策略模式可以動態(tài)地讓一個對象在許多行為中選擇一種行為,一個系統(tǒng)需要動態(tài)地在幾種算法中選擇一種, 避免使用難以維護(hù)的多重條件選擇語句,希望在具體策略類中封裝 算法和與相關(guān)的數(shù)據(jù)結(jié)構(gòu)。