寫在前面
如果你正在為代碼的可擴展性和可維護性感到煩惱,策略模式可以成為你的得力助手。本篇技術文章詳細介紹了策略模式的核心原理和實戰應用,幫助你解決在程序設計中所面臨的挑戰。無論你是初學者還是有一定經驗的開發者,這篇文章都能夠為你提供有益的知識和實用的技巧,值得一讀!
前言
用于處理類或對象的組合的結構型的設計模式已經輸出完畢:
適配器模式揭秘:讓不兼容的組件完美協同
剖析裝飾器模式:讓你的代碼更靈活、可擴展
探秘代理模式:核心原理與應用實踐
優雅的程序設計:掌握門面模式的奧秘
橋梁模式:解耦抽象與實現的秘訣
組合模式揭秘:如何構建可擴展的樹形結構
提升軟件性能的秘密武器:揭秘實戰中的享元模式
從這篇文章開始來盤一盤行為型設計模式,那么行為型的設計模式有哪些呢?行為型模式是用于描述類或對象怎樣交互以及怎樣分配職責,共十一種,包括策略模式、模版方法模式、觀察者模式、迭代器模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、解釋器模式。
什么是策略模式
策略模式是一種行為型設計模式,它定義了一系列算法,并將每個算法封裝起來,使它們可以相互替換。策略模式的主要目的是將算法的行為和環境分開,將一系列算法封裝在策略類中,并在運行時根據客戶端的需求選擇相應的算法。策略模式適用于需要使用多種算法,且算法之間可以相互替換的情況。在策略模式中,算法的變化不會影響到使用算法的客戶端。
策略模式的核心原理
策略模式是一種行為設計模式,其核心原理是將可以相互替換的算法封裝成獨立的類,并使它們能夠互相之間替換,以使得算法的變化獨立于使用算法的客戶端。
策略模式主要包括三個核心角色:
- Context(上下文):這個角色是策略模式中的重要組成部分,通常用于存儲和傳遞策略對象,以及處理策略對象的交互邏輯。上下文對象在客戶端的請求下,會調用合適的策略對象來執行相應的操作。
- Strategy(策略):這個角色通常是一個接口,用于定義各種策略對象的共同方法。具體策略對象實現這個接口,并包含具體的算法實現。策略對象不持有任何上下文對象的狀態,這樣保證了策略對象的可復用性。
- ConcreteStrategy(具體策略):這個角色是實現策略接口的具體類,包含了具體的算法實現。具體策略對象通常會持有上下文對象的狀態,以便在執行算法時能夠訪問和修改這些狀態。
這三個核心角色共同實現了策略模式的核心思想:將算法與使用算法的客戶端分離,使算法可以獨立于客戶端而變化。
策略模式如何實現
需求描述
很多購物網站都有會員業務,不同等級的會員可以享受不同程度的優惠,這里假設某會員業務系統的會員等級有非會員、初級會員、中級會員、高級會員四個等級,其中非會員在支付的時候需要全額支付 ,初級會員可以享受8折優惠,中級會員可以享受7折優惠,高級會員可以享受5折優惠,如果需要寫一個支付接口,需要怎么實現呢?
實現方案
類似這樣的業務模型,是比較適合使用策略模式的,但是如果僅僅使用策略模式是沒有辦法在主業務流程中完全避免if else的判斷的,如果從實際業務出發,可以把簡單工廠模式和策略模式結合起來使用。策略模式只負責定義不同的優惠策略,而簡單工廠模式,負責根據不同的會員,生產出不同的具體優惠策略。具體怎么做呢?
1、定義抽象的支付策略接口:PayStrategy.java;
/** * 支付策略接口 */public interface PayStrategy {
/**
* 實際支付金額計算
* @param money
*/
Double compute(Double money);
}
2、定義具體的支付策略類:Level0Streategy.java、Level1Streategy.java、Level2Streategy.java、Level3Streategy.java
/** * 非會員計費策略 */public class Level0Strategy implements PayStrategy{
@Override
public Double compute(Double money) {
System.out.println("非會員開始計費");
return money;
}
}
/** * 初級會員計費策略 */public class Level1Strategy implements PayStrategy{
@Override
public Double compute(Double money) {
System.out.println("初級會員開始計費");
return money*0.8;
}
}
/** * 中級會員計費策略 */public class Level2Strategy implements PayStrategy{
@Override
public Double compute(Double money) {
System.out.println("中級會員開始計費");
return money*0.7;
}
}
/** * 高級會員計費策略 */public class Level3Strategy implements PayStrategy{
@Override
public Double compute(Double money) {
System.out.println("高級會員開始計費");
return money*0.5;
}
}
3、定義用于存儲和傳遞策略的上下文:StreateContext.java
/** * 支付策略上下文 */public class StrategyContent {
private PayStrategy payStrategy;
public StrategyContent(PayStrategy payStrategy) {
this.payStrategy = payStrategy;
}
/**
* 支付方法
* @param money
* @return
*/
public Double pay(Double money){
return this.payStrategy.compute(money);
}
}
4、定義策略工廠類,用于生產具體的策略:PayStreategyFactory.java
/** * 策略工廠 */public class PayStrategyFactory {
public static PayStrategy getStrategy(Member member){
PayStrategy payStrategy;
switch (member.getLevel()){
case "初級":
payStrategy=new Level1Strategy();
break;
case "中級":
payStrategy=new Level2Strategy();
break;
case "高級":
payStrategy=new Level3Strategy();
break;
default:
payStrategy=new Level0Strategy();
break;
}
return payStrategy;
}
}
5、編寫客戶端:,模擬不同的用戶進行支付:Test.java
@Data@AllArgsConstructorpublic class Member { /**
* 會員姓名
*/
private String name;
/**
* 會員等級:非會員、初級、中級、高級
*/
private String level;
/**
* 支付金額
*/
private Double pay;
}
public class Test { public static void main(String[] args) { Member member = new Member("小明", "初級", 100.00); PayStrategy strategy = PayStrategyFactory.getStrategy(member);
StrategyContent strategyContent = new StrategyContent(strategy);
Double pay = strategyContent.pay(member.getPay());
System.out.println(member.getName() + "應支付金額:" + member.getPay() + ",實際支付金額:" + pay);
member = new Member("小紅", "中級", 100.00);
strategy = PayStrategyFactory.getStrategy(member);
strategyContent = new StrategyContent(strategy);
pay = strategyContent.pay(member.getPay());
System.out.println(member.getName() + "應支付金額:" + member.getPay() + ",實際支付金額:" + pay);
member = new Member("鐵蛋", "高級", 100.00);
strategy = PayStrategyFactory.getStrategy(member);
strategyContent = new StrategyContent(strategy);
pay = strategyContent.pay(member.getPay());
System.out.println(member.getName() + "應支付金額:" + member.getPay() + ",實際支付金額:" + pay);
member = new Member("李2", "非會員", 100.00);
strategy = PayStrategyFactory.getStrategy(member);
strategyContent = new StrategyContent(strategy);
pay = strategyContent.pay(member.getPay());
System.out.println(member.getName() + "應支付金額:" + member.getPay() + ",實際支付金額:" + pay);
}
}
策略模式的適用場景
- 不同業務邏輯:在同一個業務邏輯中,可能會存在不同的策略或算法。例如,在電商網站中,可以根據不同的促銷策略對商品進行不同的定價。在這種情況下,可以使用策略模式來封裝不同的促銷策略,并在運行時根據需要選擇合適的策略。
- 數據排序策略:在處理大量數據時,可能需要使用不同的排序算法。例如,冒泡排序、選擇排序、插入排序和二叉樹排序等。在這種情況下,可以使用策略模式來定義不同的排序策略,并在運行時根據需要選擇合適的策略。
- 算法切換:在某些情況下,可能需要根據不同的條件切換不同的算法。例如,在進行實時計算時,可能需要根據不同的輸入數據選擇不同的計算算法。在這種情況下,可以使用策略模式來封裝不同的算法,并在運行時根據需要選擇合適的算法。
- 行為切換:在系統中,可能需要根據不同的條件切換不同的行為。例如,在一個游戲中,可能需要根據不同的關卡選擇不同的游戲策略。在這種情況下,可以使用策略模式來封裝不同的游戲策略,并在運行時選擇合適的行為。
總之,策略模式的應用場景非常廣泛,可以用于處理不同業務邏輯、數據排序、算法切換和行為切換等方面。通過使用策略模式,我們可以將算法或行為的變化和具體實現細節分離出來,使得代碼更加靈活、易于維護和擴展。
總結
優點:
- 避免使用多重條件語句:策略模式通過使用策略類和上下文對象來避免使用多重條件語句,如if-else語句或switch-case語句。通過將算法的行為封裝到策略類中,并在運行時根據客戶端的需求選擇相應的算法,策略模式使得代碼更加簡潔、易于維護和擴展。
- 提供可重用的算法族:策略模式通過定義抽象策略類和具體策略類,提供了一系列的算法實現。這些算法可以在不同的上下文中重復使用,通過組合和替換不同的策略對象來滿足客戶端的需求。
- 分離算法和客戶端:策略模式將算法的實現和使用分離到具體的策略類和上下文對象中。客戶端只需要與上下文對象進行交互,而不需要直接處理算法的實現細節。這種分離使得代碼更加清晰、易于理解和維護。
- 支持對開閉原則的完美支持:策略模式可以在不修改原有代碼的情況下,靈活地增加新的算法。通過定義新的策略類和上下文對象,可以輕松地將新的算法集成到現有系統中,滿足新的需求。
- 將算法的使用放到環境類中:策略模式將算法的使用放到上下文對象中,而算法的實現則移到具體策略類中。這種分離使得代碼更加清晰、易于管理和擴展。
- 客戶端必須理解所有策略算法的區別:策略模式要求客戶端必須理解所有可用的策略算法的區別,以便在適當的時候選擇合適的算法。這可能增加了客戶端的復雜性和學習成本。
缺點
- 可能導致過多的策略類:策略模式可能導致創建過多的策略類,每個算法都對應一個策略類。這可能會增加系統的復雜性和維護成本。
總之,策略模式是一種行為型設計模式,它通過封裝一系列可重用的算法實現,并將它們組合到不同的上下文中,實現了算法的行為和使用的分離。這種模式使得代碼更加靈活、易于維護和擴展,同時支持在不修改原有代碼的情況下增加新算法,從而提高了代碼的靈活性和可維護性。
寫在最后
感謝您閱讀我們的技術文章!這篇文章詳細介紹了策略模式的核心原理和實戰應用,對于程序設計中所面臨的問題提出了有益的解決方案。如果您覺得這篇文章有價值,請幫忙點贊和收藏,讓更多人看到并受益。您的支持是我不斷前行的動力和鼓勵。再次感謝您的閱讀和支持,期待我們的下一次相遇!