在軟件開發(fā)中,經(jīng)常會(huì)遇到需要根據(jù)不同的條件來實(shí)現(xiàn)不同行為的場(chǎng)景。這種場(chǎng)景下,策略模式(Strategy Pattern)就是一種非常有用的設(shè)計(jì)模式。
策略模式屬于行為型模式,允許我們定義一系列算法,并將其封裝在獨(dú)立的策略類中,使得它們可以互相替換。通過使用策略模式,我們能夠靈活地選擇和切換不同的算法,而無需修改原有的代碼,替代?量 if else 的邏輯。
策略模式通常在以下情況下被使用:
例如:
這些只是策略模式的一些例子,實(shí)際應(yīng)用場(chǎng)景非常豐富。通過使用策略模式,我們可以將算法或行為與具體的業(yè)務(wù)邏輯解耦,使得系統(tǒng)更加靈活和可擴(kuò)展。
在策略模式中,有三個(gè)核心角色:上下文(Context)、策略接口(Strategy)和具體策略類(Concrete Strategy)。
下面我們來實(shí)現(xiàn)一下策略模式:
創(chuàng)建策略接口。
//策略接口public interface PaymentStrategy { void pay(double amount);}
創(chuàng)建策略接口實(shí)現(xiàn)類。
//具體策略類public class CreditCardPayment implements PaymentStrategy { public void pay(double amount) { System.out.println("使用信用卡支付:" + amount); // 具體的支付邏輯 }}
public class WeChatPay implements PaymentStrategy { public void pay(double amount) { System.out.println("使用微信支付:" + amount); // 具體的支付邏輯 }}
注意:在實(shí)際項(xiàng)目中,我們一般通過工廠方法模式來實(shí)現(xiàn)策略類的聲明。
實(shí)現(xiàn)關(guān)系如下:
圖片
創(chuàng)建 Context 類。
// 上下文類public class PaymentContext { private PaymentStrategy paymentStrategy; public PaymentContext(PaymentStrategy paymentStrategy) { this.paymentStrategy = paymentStrategy; } public void pay(double amount) { paymentStrategy.pay(amount); }}
調(diào)用一下:
// 使用示例public class Main { public static void main(String[] args) { PaymentStrategy strategy = new CreditCardPayment(); PaymentContext context = new PaymentContext(strategy); context.pay(100.0); strategy = new WeChatPay(); context = new PaymentContext(strategy); context.pay(200.0); }}
輸出:
使用信用卡支付:100.0使用微信支付:200.0
在上面的代碼中,我們定義了一個(gè) PaymentStrategy 接口作為策略接口,兩個(gè)具體的策略類 CreditCardPayment 和 WeChatPay 實(shí)現(xiàn)了該接口。然后,我們創(chuàng)建了一個(gè) PaymentContext 上下文對(duì)象,并根據(jù)需要傳入不同的策略實(shí)例進(jìn)行支付操作。
策略模式的優(yōu)點(diǎn)包括:
策略模式的缺點(diǎn)包括:
注意事項(xiàng): 如果一個(gè)系統(tǒng)的策略多于四個(gè),就需要考慮使用混合模式,解決策略類膨脹的問題,否則日后的系統(tǒng)維護(hù)就會(huì)成為一個(gè)燙手山芋。
我們可以將策略實(shí)現(xiàn)類放進(jìn) Map 中,根據(jù) key 去選擇具體的策略,就不必事先定義 Context 類。
public static void main(String[] args) { Map<String, PaymentStrategy> map=new HashMap<>(); map.put("CREDIT_CARD", new CreditCardPayment()); map.put("WECHAT_PAY",new WeChatPay()); map.get("CREDIT_CARD").pay(100.0); map.get("WECHAT_PAY").pay(200.0); }
策略枚舉可以解決策略類過多的問題。
我們對(duì)原裝的策略模式進(jìn)行改造,把原有定義在抽象策略中的方法移植到枚舉中,讓枚舉成員成為一個(gè)具體策略。
@Slf4jpublic enum PaymentStrategyEnum { CREDIT_CARD { @Override public void pay(double amount) { log.info("使用信用卡支付:" + amount); // 具體的支付邏輯 } }, WECHAT_PAY { @Override public void pay(double amount) { log.info("使用微信支付:" + amount); // 具體的支付邏輯 } }; public abstract void pay(double amount);}
在上面的代碼中,我們定義了一個(gè)枚舉類型 PaymentStrategy,其中包含兩個(gè)枚舉常量 CREDIT_CARD 和 WECHAT_PAY。每個(gè)枚舉常量都重寫了 pay() 方法,用于具體的支付邏輯。
// 使用示例public static void main(String[] args) { Map<String, PaymentStrategyEnum> map=new HashMap<>(); map.put("CREDIT_CARD", PaymentStrategyEnum.CREDIT_CARD); map.put("WECHAT_PAY", PaymentStrategyEnum.WECHAT_PAY); map.get("CREDIT_CARD").pay(100.0); map.get("WECHAT_PAY").pay(200.0); }
注意:策略枚舉是一個(gè)非常優(yōu)秀和方便的模式,但是它受枚舉類型的限制,每個(gè)枚舉項(xiàng)都是 public、final、static 的,擴(kuò)展性受到了一定的約束,因此在系統(tǒng)開發(fā)中,策略枚舉一般擔(dān)當(dāng)不經(jīng)常發(fā)生變化的角色。
SpringBoot中使用策略模式更加方便:
public interface Test { void print(String name);}
@Service("testA")@Slf4jpublic class TestA implements Test{ @Override public void print(String name) { log.info("實(shí)現(xiàn)類A"+name); }}
@Service("testB")@Slf4jpublic class TestB implements Test{ @Override public void print(String name) { log.info("實(shí)現(xiàn)類B"+name); }}
使用的時(shí)候 @Autowired 或者 @Resource 即可,SpringBoot會(huì)幫我們把實(shí)現(xiàn)類自動(dòng)注入注入Map。
@Resourceprivate Map<String,Test> map;
Test test = map.get("你想拿出的具體策略類");test.print("hello world");
策略模式是一種強(qiáng)大而靈活的設(shè)計(jì)模式,它可以幫助我們處理不同的算法或行為,并使系統(tǒng)更具可維護(hù)性和擴(kuò)展性。通過封裝具體的策略類和使用上下文對(duì)象,我們可以輕松地選擇和切換不同的策略,而無需修改現(xiàn)有的代碼。
本文鏈接:http://www.www897cc.com/showinfo-26-70477-0.html一文搞懂設(shè)計(jì)模式—策略模式
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com