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