策略模式是什么?怎么使用?

作者:溪~源
blog.csdn.net/xuan_lu/article/details/114417396
定義
首先介紹一下眾多博客文章中提到的策略模式的概念,針對于文章結(jié)構(gòu)構(gòu)成,請?jiān)试S小編在此處再細(xì)說一下。
策略模式:百度百科中引述為:指對象有某個(gè)行為,但是在不同的場景中,該行為有不同的實(shí)現(xiàn)算法。
策略模式是對算法的包裝,是把使用算法的責(zé)任和算法本身分割開來,委派給不同的對象管理。 策略模式通常把一個(gè)系列的算法包裝到一系列的策略類里面,作為一個(gè)抽象策略類的子類。用一句話來說,就是:“準(zhǔn)備一組算法,并將每一個(gè)算法封裝起來,使得它們可以互換”。
【此處的算法,大家可以理解為解決業(yè)務(wù)需求的方法。】
對于這些概念大家理解起來或許有些抽象,耐心往下讀,相信大家肯定會有所收獲。
組成
環(huán)境(Context)角色: 持有一個(gè)Strategy的引用。 抽象策略(Strategy)角色: 這是一個(gè)抽象角色,通常由一個(gè)接口或抽象類實(shí)現(xiàn)。此角色給出所有的具體策略類所需的接口。 具體策略(ConcreteStrategy)角色: 包裝了相關(guān)的算法或行為。
理解
對于設(shè)計(jì)模式中的策略模式,大家眾多的解釋可能側(cè)重與解決if…else,switch-cas這種條件語句的優(yōu)化,小編簡單談一下我在項(xiàng)目中實(shí)際應(yīng)用和理解吧;對于策略模式按照上面給予的定義理解,是將多個(gè)業(yè)務(wù)節(jié)點(diǎn)具備的共同算法再次頂層抽象為接口,處理不同業(yè)務(wù)需求時(shí),則產(chǎn)生的行為不同,即具體行為由其實(shí)現(xiàn)類解決;注重詞:相同算法,,頂層抽出。
再簡單舉例說明一下,比如工作的OA系統(tǒng)中,流程節(jié)點(diǎn)具體相同的功能:提交,回退,撤回等等(抽象策略類);但是每個(gè)流程節(jié)點(diǎn)所實(shí)現(xiàn)的功能不同(具體策略類);
實(shí)現(xiàn)
小編以我們?nèi)粘I钪凶畛R姷闹Ц斗绞綖槔獯鸩呗阅J降膽?yīng)用。
無論使用xiaomi,huawei,apple均存在相同的行為(算法),例如:支付方式不同,客戶端享受的優(yōu)惠力度不等。故我們將支付作為共同的接口抽象出來。
UML

抽象策略類
將支付作為共同算法,頂層抽象。
/**
* @author wx
* @date 2021/03/05 1:50 下午
*/
public interface PayStrategy {
void pay(double money);
}
具體策略類
MiPAY
/**
* @author wx
* @date 2021/03/05 1:51 下午
*/
public class MiPayStrategy implements PayStrategy{
@Override
public void pay(double money) {
double payMoney = money * 0.87;
double discountMoney = money - payMoney;
System.out.println("使用Mi pay成功支付" + payMoney + "元,優(yōu)惠" + discountMoney + "元");
}
}
HuaWeiPAY
/**
* @author wx
* @date 2021/03/05 1:50 下午
*/
public class HuaWeiPayStrategy implements PayStrategy{
@Override
public void pay(double money) {
double payMoney = money * 0.85;
double discountMoney = money - payMoney;
System.out.println("使用HuaWei pay成功支付" + payMoney + "元,優(yōu)惠" + discountMoney + "元");
}
}
ApplePAY
/**
* @author wx
* @date 2021/03/05 1:52 下午
*/
public class ApplePayStrategy implements PayStrategy{
@Override
public void pay(double money) {
double payMoney = money * 0.82;
double discountMoney = money - payMoney;
System.out.println("使用Apple pay成功支付" + payMoney + "元,優(yōu)惠" + discountMoney + "元");
}
}
環(huán)境類
供客戶端調(diào)用,并選擇具體策略
/**
* @author wx
* @date 2021/03/05 1:53 下午
*/
public class PayContext {
//依賴策略接口屬性
private PayStrategy payStrategy;
public void setPayStrategy(PayStrategy payStrategy) {
this.payStrategy = payStrategy;
}
/**
* 提供外部訪問方法
* @param money
*/
public void payMoney(double money) {
payStrategy.pay(money);
}
}
客戶端
客戶端則已知選擇的支付方式,可以服務(wù)端依據(jù)不同支付策略選擇折扣。
/**
* @author wx
* @date 2021/03/05 1:59 下午
*/
public class PayClient {
public static void main(String[] args) {
//創(chuàng)建支付上下文
PayContext payContext = new PayContext();
//創(chuàng)建支付策略,客戶端已知存在具體策略
PayStrategy miPayStrategy = new MiPayStrategy();
payContext.setPayStrategy(miPayStrategy);
payContext.payMoney(100);
System.out.println("-------改變支付策略--------");
PayStrategy applePayStrategy = new ApplePayStrategy();
payContext.setPayStrategy(applePayStrategy);
payContext.payMoney(100);
}
}
執(zhí)行結(jié)果:

理解了策略模式的使用,下面簡單談?wù)勗撃J降膬?yōu)點(diǎn)和缺點(diǎn):
優(yōu)點(diǎn):
毫不疑問復(fù)合設(shè)計(jì)模式中的開閉原則,新增支付方式則擴(kuò)展策略類即可,無須改動(dòng)其他策略類的實(shí)現(xiàn); 消除if-else類似的判斷語句,整合代碼結(jié)構(gòu),符合代碼整潔之道;
缺點(diǎn):
從類的數(shù)量上而言,若策略選擇很多,則造成策略類數(shù)量增加; 所有策略類都需要對外暴露。即客戶端必須知道所有的策略類,并自行決定使用哪一個(gè)策略類,故不得不向客戶暴露具體的實(shí)現(xiàn)。
類比其他模式
策略模式和狀態(tài)模式:
一、執(zhí)行方式:
策略模式:客戶端策略條件選擇只執(zhí)行一次; 狀態(tài)模式:隨著實(shí)例參數(shù)(對象實(shí)例的狀態(tài))的改變不停地更改執(zhí)行模式。
簡言之,策略模式只是在對象初始化的時(shí)候更改執(zhí)行模式,而狀態(tài)模式是根據(jù)對象實(shí)例的周期時(shí)間而動(dòng)態(tài)地改變對象實(shí)例的執(zhí)行模式。
二、環(huán)境類
策略模式:環(huán)境類自己選擇一個(gè)具體策略類,具體策略類無須關(guān)心環(huán)境類 ; 狀態(tài)模式:環(huán)境類由于外在因素需要放進(jìn)一個(gè)具體狀態(tài)中,以便通過其方法實(shí)現(xiàn)狀態(tài)的切換 ,因此環(huán)境類和狀態(tài)類之間存在一種雙向的關(guān)聯(lián)關(guān)系。
簡言之,使用策略模式時(shí)客戶端需要知道所選的具體策略是哪一個(gè);
而使用狀態(tài)模式時(shí), 客戶端無須關(guān)心具體狀態(tài) ,環(huán)境類的狀態(tài)會根據(jù)用戶的操作自動(dòng)轉(zhuǎn)換。
