策略模式定義了算法家族,分別封裝起來,讓它們之間可以相互替換,此模式讓算法的變化,不會影響到使用算法的客戶。策略模式是一種定義一系列算法的方法,從概念來看,所有這些算法完成的都是相同的工作,只是實現不同,它可以以相同的方式調用所有的算法,減少各種算法類與使用算法類之間的耦合。
一、引
我們必須要真正理解模式的思路,才能在不同情況下選擇合適的模式。我們使用模式的目的就是是代碼層次思路清晰,並且儘可能的減少已完成代碼需要修改重新編譯的情況,進而降低代碼被無意或者有意的修改破壞。還有一個是我個人的使用習慣,就是儘量使主程序的代碼簡潔清晰,從而降低耦合度。
二、問題
我們來思考一下,現在需要一個用於計算交易額的程序,計算交易額的算法有多種,其中包括等價交易、打折交易等方式,而且計算交易額的算法隨時都需要添加其他的算法,如添加滿消費返現的算法。爲了實現功能,並保證程序的低耦合、可維護性、安全性等等,你會如何設計?
三、理解
我們仔細思考一下這個程序的需求,可以將其簡化爲,輸入金額-->選擇一種計算算法-->得到交易額,經過分析,其中的思路其實已經非常明顯了,我們可以知道雖然有多種計算算法,但是這些算法都是爲了得到一個數值,只是實現方式不同而已(理解策略模式的定義),所以我們只需要設計一個抽象的類,然後分別寫不同算法的子類繼承它,並使用一個實用類使用它即可。(有人會說可以用簡單工廠模式,當然可以,只不過我每次添加新的算法的時候,我都需要去修改工廠類中的switch判斷,所以每次都需要重新編譯工廠類,還是存在風險)
四、實現
我們需要一個抽象父類,一些算法子類,一個實用類
抽象父類代碼:
public abstract class Strategy {
public abstract double AlgorithmInterface(double money);
}
各算法子類
//等價交易
public class NormalCash extends Strategy {
@Override
public double AlgorithmInterface(double money) {
return money;
}
}
//打折交易
public class RebateCash extends Strategy {
private double moneyRebate = 1d;
public RebateCash(String moneyRebate) {
this.moneyRebate = Double.parseDouble(moneyRebate);
}
@Override
public double AlgorithmInterface(double money) {
return money * moneyRebate;
}
}
//滿消費返現交易
public class ReturnCash extends Strategy {
private double moneyCondition = 0.0d;
private double moneyReturn = 0.0d;
public ReturnCash(String moneyCondition, String moneyReturn) {
this.moneyCondition = Double.parseDouble(moneyCondition);
this.moneyReturn = Double.parseDouble(moneyReturn);
}
@Override
public double AlgorithmInterface(double money) {
double result = money;
if(money >= moneyCondition) {
result = money - Math.floor(money / moneyCondition) * moneyReturn;
}
return result;
}
}
實用類:
public class ContextCash {
private Strategy strategy;
public ContextCash(Strategy strategy) {
this.strategy = strategy;
}
public double GetResult(double money) {
return strategy.AlgorithmInterface(money);
}
}
最後在主程序中測試使用:
public class Main {
public static void main(String[] args) {
double total = 0.0d;
ContextCash cash = null;
cash = new ContextCash(new NormalCash());
System.out.println(cash.GetResult(1.12));
cash = new ContextCash(new RebateCash("0.8"));
System.out.println(cash.GetResult(1.12));
cash = new ContextCash(new ReturnCash("300", "100"));
System.out.println(cash.GetResult(310));
}
}