1. 程式人生 > >設計模式二之策略模式

設計模式二之策略模式

策略模式

它定義了演算法家族,分別封裝起來,讓它們之間可以互相替換,此模式讓演算法的變化,不會影響到使用演算法阿德客戶。

程式碼示例

需求

實現一個簡易收銀軟體

UML

策略模式機構圖

在這裡插入圖片描述

程式碼

package strategyPattern;
/**
 * Created by yutong on 2018/11/6
 * 抽象演算法類
 */
abstract class CashFee {
    public abstract double getResult(double money);
}
package strategyPattern;
/** * Created by yutong on 2018/11/6 * 正常收費 */ public class CashNormal extends CashFee{ public CashNormal() { } @Override public double getResult(double money) { return money; } }
package strategyPattern;
package strategyPattern;
/**
 * Created by yutong on 2018/11/6
 * 打折收費類
 */
public class CashRebate extends CashFee { private double moneyRebate; public CashRebate(double moneyRebate) { this.moneyRebate = moneyRebate; } @Override public double getResult(double money) { return money*moneyRebate; } }
package strategyPattern;
/**
 * Created by yutong on 2018/11/6
 * 返利收費
 */
public class CashReturn extends CashFee { private double basePrice; private double returnPrice; public CashReturn(double basePrice,double returnPrice) { this.basePrice = basePrice; this.returnPrice = returnPrice; } @Override public double getResult(double money) { double result = 0; if (money > basePrice){ result = money - Math.floor(money/basePrice)*returnPrice; } return result; } }
package strategyPattern;
/**
 * Created by yutong on 2018/11/6
 * 上下文類
 */
public class CashContext {
    private CashFee cashFee;

    public CashContext(int type,double basePrice,double returnPrice,double rebatePrice) {
        switch (type){
            case 1://正常收費
                this.cashFee = new CashNormal();
                break;
            case 2:
                this.cashFee = new CashReturn(basePrice,returnPrice);
                break;
            case 3:
                this.cashFee = new CashRebate(rebatePrice);
                break;
        }
    }

    public double acceptCash(double money){
         return cashFee.getResult(money);
    }
}
package strategyPattern;

import java.util.Scanner;

/**
 * Created by yutong on 2018/11/6
 * 結算客戶端類
 */
public class CashClient {
    public static void main(String[] args){
        System.out.println("=======這是一款神奇的收銀軟體=======");
        Scanner scanner = new Scanner(System.in);
        System.out.println("請輸入您要購買的商品原價:");
        String originalPrice = scanner.nextLine();
        System.out.println("請選擇要優惠的活動:1,正常收費;2,滿300減100;3,打8折");
        String seletItem = scanner.nextLine();
        double result = 0;
        if ("1".equals(seletItem)){
            CashContext cashContext = new CashContext(1,0,0,0);
            result = cashContext.acceptCash(Double.parseDouble(originalPrice));
        }
        if ("2".equals(seletItem)){
            CashContext cashContext = new CashContext(2,300,100,0);
            result = cashContext.acceptCash(Double.parseDouble(originalPrice));
        }
        if ("3".equals(seletItem)){
            CashContext cashContext = new CashContext(3,0,0,0.8);
            result = cashContext.acceptCash(Double.parseDouble(originalPrice));
        }
        System.out.println("您需要付款:"+result);
    }
}

總結

策略模式是一種定義一系列演算法的方法,從概念上來看,所有這些演算法完成的都是相同的工作,只是實現不同,他可以以相同的方式呼叫所有的演算法,減少了演算法類與使用演算法類之間的耦合。

對於客戶端而言: 簡單工廠設計模式, 客戶端需要知道兩個類, 而簡單工廠+策略設計模式, 客戶端只需要知道一個類, 減低了耦合性.

使用場景

策略模式就是用來封裝演算法的,但在實踐中,我們發現可以用它來封裝幾乎任何型別的規則,只要在分析過程中聽到需要在不同時間應用不同的業務規則,就可以考慮使用策略模式處理這種變化的可能性。
多個演算法可實現類似功能,若將所有方法寫在一個sortUtils裡面會導致難以維護,程式碼複雜。所以策略模式考慮如何讓演算法和物件分開來,使得演算法可以獨立於使用它的客戶而變化。具體的方案是把一個類中經常改變或者將來可能改變的部分提取出來,作為一個介面,然後在類中包含這個物件的例項,這樣類的例項在執行時就可以隨意呼叫實現了這個介面的類的行為。

優點

1、可以動態的改變物件的行為

缺點

1、客戶端必須知道所有的策略類,並自行決定使用哪一個策略類
2、策略模式將造成產生很多策略類