
本文原創(chuàng)地址:jsbintask的博客(食用效果最佳),轉(zhuǎn)載請注明出處!
前言
策略模式是一種行為模式,它用以運(yùn)行時動態(tài)的改變類的行為,通過將一系列類似的算法封裝成不同的類來達(dá)到目的,可以有效減少代碼中if else的冗余。它實(shí)現(xiàn)的關(guān)鍵是面向接口接口編程以及有一個算法切換者。它的優(yōu)點(diǎn)是擴(kuò)展性良好,可以自由切換策略。
栗子
周末天氣不錯,小明準(zhǔn)備去爬武功山,于是他請教它的出行助手應(yīng)該選擇怎樣的工具去目的地才能讓他最大化周末的快樂。于是它的出行助手開始了一段計算,操作。。。最終。。。
抽象
針對上面的案例,重點(diǎn)在于出行助手如何幫小明選擇出行工具,這恰好可以對應(yīng)我們一開始說的需要封裝的算法,并且能夠隨意切換,于是我們可以得出下面的uml類圖:

小明通過使用出行助手來選擇不同的交通工具。而出行助手內(nèi)部則通過代理
TravelStrategy接口來切換不同的出行算法。
實(shí)現(xiàn)
首先定義出行接口TravelStrategy:
@FunctionalInterface
public interface TravelStrategy {
void travel();
}
接著實(shí)現(xiàn)不同的出行算法,此處有BikeTravelStrategy, FootTravelStrategy, CarTravelStrategy。
@Slf4j
public class BikeTravelStrategy implements TravelStrategy {
@Override
public void travel() {
log.info("自行車騎行半小時,行程18公里,感覺卡路里在燃燒!");
}
}
============================================================
@Slf4j
public class FootTravelStrategy implements TravelStrategy {
@Override
public void travel() {
log.info("徒步旅行半小時,行走5公里,可以好好欣賞周邊景色");
}
}
============================================================
@Slf4j
public class CarTravelStrategy implements TravelStrategy {
@Override
public void travel() {
log.info("自駕旅行半小時,行程40公里,感覺時間走的真慢。");
}
}
接著就需要實(shí)現(xiàn)出行助手類:TravelService,它內(nèi)部通過代理TravelStategy來切換不同的策略:
public class TravelService {
private TravelStrategy travelStrategy;
public void chooseTravelStrategy(TravelStrategy travelStrategy) {
this.travelStrategy = travelStrategy;
}
public void doTravel() {
this.travelStrategy.travel();
}
}
最后,編寫一個測試類:
@Slf4j
public class App {
public static void main(String[] args) {
System.out.println("天氣不錯,小明準(zhǔn)備出門旅行,它帶上了它的旅行助手'TravelService'來幫它制定出行策略.");
TravelService travelService = new TravelService();
System.out.println("'TravelService': 天氣不錯,您可以選擇徒步出行");
travelService.chooseTravelStrategy(new FootTravelStrategy());
travelService.doTravel();
System.out.println("'TravelService': 2小時后可能轉(zhuǎn)小雨,建議您選擇自行車加快形成,鍛煉身體!");
travelService.chooseTravelStrategy(new BikeTravelStrategy());
travelService.doTravel();
System.out.println("'TravelService': 半小時后會有暴雨,建議您選擇自駕汽車去目的地.");
travelService.chooseTravelStrategy(new CarTravelStrategy());
travelService.doTravel();
System.out.println("'TravelService': 天氣已經(jīng)好轉(zhuǎn),您可以隨意選擇出行方式。");
travelService.chooseTravelStrategy(() -> {
log.info("騎行摩托車開始,半小時形成30公里。刺激!");
});
System.out.println("'TravelService': 您已到達(dá)目的地.");
}
}
注意上面的關(guān)鍵代碼為TravelService根據(jù)不同的天氣選擇了不同的出行策略。

根據(jù)結(jié)果我們可以知道我們切換了三次不同的策略,并且使用lambda表達(dá)式添加了一個匿名策略。
總結(jié)
使用策略模式的關(guān)鍵在于面向接口編程,并且有一個全局切換策略的輔助類,它的優(yōu)點(diǎn)在于擴(kuò)展性良好,算法可以自由切換動態(tài)改變類的行為。
而它的缺點(diǎn)也很明顯:策略類過多會導(dǎo)致“類爆炸“,并且所有的策略類都需要向外暴露。 所以使用時如果策略過多可以考慮使用混合模式,配合其它模式一起使用。
關(guān)注我,這里只有干貨!