從未這么明白的設(shè)計模式(四):策略模式

cover

本文原創(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類圖:

Strategy

小明通過使用出行助手來選擇不同的交通工具。而出行助手內(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ù)不同的天氣選擇了不同的出行策略。

Strategy

根據(jù)結(jié)果我們可以知道我們切換了三次不同的策略,并且使用lambda表達(dá)式添加了一個匿名策略。

總結(jié)

使用策略模式的關(guān)鍵在于面向接口編程,并且有一個全局切換策略的輔助類,它的優(yōu)點(diǎn)在于擴(kuò)展性良好,算法可以自由切換動態(tài)改變類的行為。
而它的缺點(diǎn)也很明顯:策略類過多會導(dǎo)致“類爆炸“,并且所有的策略類都需要向外暴露。 所以使用時如果策略過多可以考慮使用混合模式,配合其它模式一起使用。

關(guān)注我,這里只有干貨!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容