設(shè)計模式之策略模式

簡介

策略模式:策略模式是一種行為型模式,它將對象和行為分開,將行為定義為 一個行為接口具體行為的實現(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>

uml圖

代碼

接口類

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);
    }
}

適用場景

  1. 如果在一個系統(tǒng)里面有許多類,它們之間的區(qū)別僅在于它們 的行為,那么使用策略模式可以動態(tài)地讓一個對象在許多行 為中選擇一種行為。
  2. 一個系統(tǒng)需要動態(tài)地在幾種算法中選擇一種。
  3. 如果一個對象有很多的行為,如果不用恰當(dāng)?shù)哪J?,這些行 為就只好使用多重的條件選擇語句來實現(xiàn)。
  4. 不希望客戶端知道復(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é)

  1. 策略模式的關(guān)鍵是:分析項目中變化部分與不變部分

  2. 策略模式的核心思想是:多用組合/聚合少用繼承;用行為類組合,而不是行為的繼承更有彈性

  3. 體現(xiàn)了“對修改關(guān)閉,對擴(kuò)展開放”原則,客戶端增加行為不用修改原有代碼,只 要添加一種策略(或者行為)即可,避免了使用多重轉(zhuǎn)移語句(if..else if..else)

  4. 提供了可以替換繼承關(guān)系的辦法: 策略模式將算法封裝在獨立的Strategy類中使得 你可以獨立于其Context改變它,使它易于切換、易于理解、易于擴(kuò)展

  5. 需要注意的是:每添加一個策略就要增加一個類,當(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)。

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

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

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