大話設計模式(2)——策略模式

策略模式

定義

策略模式定義了算法族,分別封裝起來,讓它們之間能夠互相替換,此模式讓算法的變化獨立於使用算法的客戶。html

策略模式的精髓就在於將常常變化的一點提取出來,單獨變成一類,而且各個類別能夠相互替換和組合,類圖關係以下:java

img

結合策略模式的類圖,可知:git

策略模式經過context上下文類來自由的選擇所要採起的方法:github

public class AbstractContext {
    AbstractStrategy strategy;

    //初始化時傳入具體的策略對象
    public AbstractContext(AbstractStrategy strategy) {
        this.strategy = strategy;
    }

    //上下文接口,調用策略的具體方法
    public void ContextInterface() {
        strategy.ItsInterface();
    }
}
複製代碼

而對應的方法都是繼承與同一個抽象的策略類算法

public abstract class AbstractStrategy {
    //留待子類本身實現
    public void ItsInterface(){
    }
}
複製代碼

具體的策略類實如今子類中進行重載,以下:設計模式

public class FakeStrategy extends AbstractStrategy{
    
    @Override
    //子類實現的具體方法
    public void ItsInterface() {
        System.out.println("I'm using this method");
    }
}
PS:其餘各種方法同理
複製代碼

場景

策略模式所要解決的問題主要是在多種算法極其類似的狀況下,讓對象根據上下文(context)進行具體實現的選擇。例如選擇出門的方式:騎車、開車、走路等等,甚至騎車一段時間、走路一段時間、坐飛機一段時間。markdown

我以爲《大話設計模式》舉的例子十分貼切:某商場搞促銷活動,有打折活動、滿減活動(兩個可同時進行),而且打折的力度和滿減的程度可能在從此須要進行修正,那麼應當如何設計整個系統呢?ide

解決

假設如今商場有三種結算方式:正常結算、打折結算、返利結算。根據策略模式的思想,咱們能夠設計一個這樣的系統:oop

img

  1. 上下文類Context

先建立一個抽象的上下文類,獲取傳入的具體優惠策略,調用getPrice()來獲取結果。post

public class CashContext {

    private CashAbstract CashAbstract;

    public CashContext(CashAbstract CashAbstract) {
        this.CashAbstract = CashAbstract;
    }

    public double getResult(double money) {
        return CashAbstract.acceptCash(money);
    }
}
複製代碼
  1. 抽象策略類

抽象策略類在這裏指的是所採用的收費方式:

public abstract class CashAbstract {
    public abstract double acceptCash(double money);
}
複製代碼
  1. 三種具體的策略子類

商場活動一共有三種:正常收費(無活動)、打折收費、返利收費,這裏只給出返利收費的實現:

public class CashReturn extends CashAbstract {

    //返利收費,初始化時必須輸入返利條件以及返利金額
    private double moneyCondition = 0.0;
    private double moneyReturn = 0.0d;

    public CashReturn(double moneyCondition, double moneyReturn) {
        this.moneyCondition = moneyCondition;
        this.moneyReturn = moneyReturn;
    }

    @Override
    public double acceptCash(double money) {
        double result = money;

        if (money >= moneyCondition) {
            result = money - Math.floor(money / moneyCondition) * moneyReturn;
        }

        return result;
    }
}
複製代碼
  1. 測試一下咱們的設計的收費系統
public class App {
    public static void main(String[] args) {
        CashContext cashContext = null;

        Scanner scanner = new Scanner(System.in);
        System.out.print("請輸入活動內容:1是正常收費,2是返利收費,3是打折活動");
        int in = scanner.nextInt();
        String type = "";

        switch (in) {
            case 1:
                cashContext = new CashContext(new CashNormal());
                type += "正常收費";
                break;

            case 2:
                cashContext = new CashContext(new CashReturn(300, 100));
                type += "滿300返100";
                break;

            case 3:
                cashContext = new CashContext(new CashRebate(0.8));
                type += "打8折";
                break;

            default:
                System.out.println("請輸入1/2/3");
                break;
        }

        double totalPrices = 0;

        System.out.print("請輸入單價:");
        double price = scanner.nextDouble();
        System.out.print("請輸入數量:");
        double num = scanner.nextDouble();
        totalPrices = cashContext.getPrice(price * num);

        System.out.println("單價:" + price + ",數量:" + num + ",類型:" + type + ",合計:" + totalPrices);

        scanner.close();
    }
}
複製代碼

正常:

img

返利:

img

打折:

img

可見,咱們設計的收費系統是沒問題的。

優缺點

策略模式的優勢就在於能夠靈活的選擇須要使用的算法,減小ifelse語句

缺點就是,若是具體的策略類較多的話,各個策略類之間不具備複用性

思考

策略模式使用了哪些設計原則?

項目地址

github.com/white0dew/D…

參考連接

《大話設計模式》

《Head First 設計模式》

閒說設計模式:

www.cnblogs.com/adamjwh/p/1…

往期文章

大話設計模式(1)——單例模式 #掘金文章# juejin.cn/post/696772…

相關文章
相關標籤/搜索