【設計模式系列】行爲型之策略模式
定義
首先介紹一下衆多博客文章中提到的策略模式的概念,針對於文章結構構成,請允許小編在此處再細說一下。
策略模式:百度百科中引述爲:指對象有某個行爲,但是在不同的場景中,該行爲有不同的實現算法。
- 策略模式是對算法的包裝,是把使用算法的責任和算法本身分割開來,委派給不同的對象管理。
- 策略模式通常把一個系列的算法包裝到一系列的策略類裏面,作爲一個抽象策略類的子類。用一句話來說,就是:“準備一組算法,並將每一個算法封裝起來,使得它們可以互換”。
【此處的算法,大家可以理解爲解決業務需求的方法。】
對於這些概念大家理解起來或許有些抽象,耐心往下讀,相信大家肯定會有所收穫。
組成
- 環境 (Context) 角色:持有一個 Strategy 的引用。
- 抽象策略 (Strategy) 角色:這是一個抽象角色,通常由一個接口或抽象類實現。此角色給出所有的具體策略類所需的接口。
- 具體策略 (ConcreteStrategy) 角色:包裝了相關的算法或行爲。
理解
對於設計模式中的策略模式,大家衆多的解釋可能側重與解決 if…else,switch-cas 這種條件語句的優化,小編簡單談一下我在項目中實際應用和理解吧;對於策略模式按照上面給予的定義理解,是將多個業務節點具備的共同算法再次頂層抽象爲接口,處理不同業務需求時,則產生的行爲不同,即具體行爲由其實現類解決;注重詞:相同算法,,頂層抽出。
再簡單舉例說明一下,比如工作的 OA 系統中,流程節點具體相同的功能:提交,回退,撤回等等(抽象策略類);但是每個流程節點所實現的功能不同(具體策略類);
實現
小編以我們日常生活中最常見的支付方式爲例,解答策略模式的應用。
無論使用 xiaomi,huawei,apple 均存在相同的行爲(算法),例如:支付方式不同,客戶端享受的優惠力度不等。故我們將支付作爲共同的接口抽象出來。
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 + "元,優惠" + 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 + "元,優惠" + 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 + "元,優惠" + discountMoney + "元");
}
}
環境類
供客戶端調用,並選擇具體策略
/**
* @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);
}
}
客戶端
客戶端則已知選擇的支付方式,可以服務端依據不同支付策略選擇折扣。
/**
* @author wx
* @date 2021/03/05 1:59 下午
*/
public class PayClient {
public static void main(String[] args) {
//創建支付上下文
PayContext payContext = new PayContext();
//創建支付策略,客戶端已知存在具體策略
PayStrategy miPayStrategy = new MiPayStrategy();
payContext.setPayStrategy(miPayStrategy);
payContext.payMoney(100);
System.out.println("-------改變支付策略--------");
PayStrategy applePayStrategy = new ApplePayStrategy();
payContext.setPayStrategy(applePayStrategy);
payContext.payMoney(100);
}
}
執行結果:
理解了策略模式的使用,下面簡單談談該模式的優點和缺點:
- 優點:
- 毫不疑問複合設計模式中的開閉原則,新增支付方式則擴展策略類即可,無須改動其他策略類的實現;
- 消除 if-else 類似的判斷語句,整合代碼結構,符合代碼整潔之道;
- 缺點:
- 從類的數量上而言,若策略選擇很多,則造成策略類數量增加;
- 所有策略類都需要對外暴露。即客戶端必須知道所有的策略類,並自行決定使用哪一個策略類,故不得不向客戶暴露具體的實現。
類比其他模式
策略模式和狀態模式:
一、執行方式:
策略模式:客戶端策略條件選擇只執行一次;
狀態模式:隨着實例參數(對象實例的狀態)的改變不停地更改執行模式。
簡言之,策略模式只是在對象初始化的時候更改執行模式,而狀態模式是根據對象實例的週期時間而動態地改變對象實例的執行模式。
二、環境類
策略模式:環境類自己選擇一個具體策略類,具體策略類無須關心環境類 ;
狀態模式:環境類由於外在因素需要放進一個具體狀態中,以便通過其方法實現狀態的切換 ,因此環境類和狀態類之間存在一種雙向的關聯關係。
簡言之,使用策略模式時客戶端需要知道所選的具體策略是哪一個;
而使用狀態模式時, 客戶端無須關心具體狀態 ,環境類的狀態會根據用戶的操作自動轉換。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://blog.csdn.net/xuan_lu/article/details/114417396