設計模式之 - 策略模式
一、什麼是策略模式
策略模式:它定義了演算法家族,分別封裝起來,讓他們之間可以互相替換,此模式的變化,不會影響到使用演算法的客戶。
我們來看下策略模式的UML圖:
二、策略模式的構成
公共策略:定義一個介面作為公共策略,所有的演算法規則實現該介面;
具體策略:封裝了具體的演算法和行為,繼承於公共策略;
封裝類:進行二次封裝,維護對公共策略物件的引用;
三、例項演示
業務場景:現在我們在做一個商場的優惠活動,這個活動根據節日的不同也會調整相應的活動規則,比如五一黃金週我們是所有會員商品一律8折,節日過後恢復原價不再優惠,等到了國慶商場有有了新的促銷活動,滿300減150,那麼根據這樣的業務需求我們來看看使用策略模式到底應該怎麼做?
首先我們需要建立一個公共的策略類
public interface Strategy { // 演算法規則 double regulation(double money);}複製程式碼
接下來我們分別定義三種活動規則,首先是沒有優惠活動的收費方式
public class NormalStrategy implements Strategy { @Override public double regulation(double money) { System.out.println("正常收費 : " + money); return money; }}複製程式碼
打折
public class DiscountStrategy implements Strategy { private double moneyDiscount = 1D; public DiscountStrategy(String discount) { this.moneyDiscount = Double.parseDouble(discount); } @Override public double regulation(double money) { System.out.println("打折優惠 : " + money * moneyDiscount); return money * moneyDiscount; }}複製程式碼
滿300返150
public class RebateStrategy implements Strategy { // 滿多少 private double moneyCondition = 0.0D; // 減多少 private double moneyRebate = 0.0D; public RebateStrategy(String moneyCondition, String moneyRebate) { this.moneyCondition = Double.parseDouble(moneyCondition); this.moneyRebate = Double.parseDouble(moneyRebate); } @Override public double regulation(double money) { // 判斷是否滿足返利條件 if (money > moneyCondition) { System.out.println("折扣返現 : " + (money - Math.floor(money / moneyCondition) * moneyRebate)); return money - Math.floor(money / moneyCondition) * moneyRebate; } System.out.println("不夠返現條件 : " + money); return money; }}複製程式碼
接下來,我們需要建立一個封裝類也可以叫上下文的類,對我們的活動規則進行一個維護
public class Context { private Strategy strategy; public Context(String type,double money) { switch (type) { case "正常收費": Strategy normalStrategy = new NormalStrategy(); strategy = normalStrategy; strategy.regulation(money); break; case "打5折": Strategy discountStrategy = new DiscountStrategy("0.5"); strategy = discountStrategy; strategy.regulation(money); break; case "滿300減150": Strategy rebateStrategy = new RebateStrategy("300", "150"); strategy = rebateStrategy; strategy.regulation(money); break; } }}複製程式碼
最後我們分別來測試看下結果是否正確:
public class Main { public static void main(String[] args) { new Context("打5折", 500); new Context("正常收費", 500); new Context("滿300減150", 500); }}複製程式碼
可能有讀者就存在疑問了,這跟簡單工廠模式又有什麼區別呢?
第一:首先在我們的封裝類中其實已經使用到了簡單工廠模式,我們使用簡單工廠模,我們通過這種方式的封裝將判斷是什麼優惠的過程從客戶端轉移到了我們的程式中,客戶不需要再去關係;
第二:我們來看下我們昨天的簡單工廠模式客戶端事怎麼呼叫的,再來看看我們今天使用策略模式是怎麼呼叫的
通過上面我們可以看到,簡單工廠模式需要客戶端認識兩個類,也就是CarFactory和Product,而簡單工廠模式只需要客戶端認識一個類,也就是Context,這樣就降低了我們程式碼的耦合性。
四、策略模式的優點
策略模式之間可以自由的切換;
增加了程式的擴充套件性,如果想要增加新的策略,只需要實現公共的策略即可;
避免使用多重條件,當所有的演算法都堆積在一個類中,那麼就不可避免的要使用條件判斷來選擇合適的演算法;
五、策略模式的缺點
如果有新的策略確實很容易進行擴充套件,但是當策略多了之後維護就變得比較艱難,所以一般策略的數量一般維護在3個左右;
必須把所有的策略暴露給使用者,使用者好知道知道使用哪種策略;