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