所有設計模式傳送門
定義一系列算法,把他們一個個封裝起來,並使它們可以相互的替換。本模式使得算法可獨立於使用它的客戶而變化。策略模式 也是處理算法不同變體的一種成熟模式。
包含的角色:
1、策略: 是一個接口,該接口定義若干個算法標識,即定義了若干個抽象方法。
2、具體策略: 是實現策略接口的類,即給出算法標識的具體算法。
3、上下文: 是依賴與策略接口的類,即上下文包含由策略聲明的變量。上下文中提供一個方法,該方法委託策略變量調用具體策略所實現的策略接口中的方法。
優點:
1、上下文和具體策略是鬆耦合的關係。因此上下文只知道它要使用 某一個實現Strategy接口類的實例,但不知道具體是哪一個類。
2、滿足開-閉原則。當增加新的策略時,不需要修改上下文類的代碼,上下文就可以引用新的具體策略的實例。
適用情景:
1、一個類定義了多種行爲,並且這些行爲在這個類的方法中以多個條件語句的形式出現,那麼可以使用該模式避免在類中大量使用條件語句。
2、程序不希望暴露覆雜的、與算法相關的數據結構,那麼可以使用該模式封裝算法。
3、需要使用一個算法的不同變體。
簡單的例子:
在某種比賽,有若干個裁判,每位裁判給選手一個得分。選手的最後得分是根據全體裁判的得分計算出來的。請給出幾種計算選手得分的評分方案(策略),對於某次比賽,可以從你的方案中選擇一種方案作爲本次比賽的評分方案。
/**
* 選手類
*/
public class Person {
String name;
double score;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
}
/**
* 策略接口-計算得分
*/
public interface ComputableStrategy {
public abstract double computeScore(double[] a);
}
/**
* 上下文
*/
public class GymnasticsGame {
ComputableStrategy strategy;
public void setStrategy(ComputableStrategy strategy){
this.strategy = strategy;
}
public double getPersonScore(double[] a){
if (strategy != null) {
return strategy.computeScore(a);
}
else {
return 0;
}
}
}
/**
* 策略一
* 計算代數平均分
*/
public class StrategyOne implements ComputableStrategy{
@Override
public double computeScore(double[] a) {
double score = 0;
double sum = 0;
for (int i = 0; i < a.length; i++) {
sum += a[i];
}
score = sum / a.length;
return score;
}
}
/**
* 策略二
* 計算幾何平均分
*/
public class StrategyTwo implements ComputableStrategy{
@Override
public double computeScore(double[] a) {
double score = 0;
double muti = 1;
int n = a.length;
for (int i = 0; i < a.length; i++) {
muti *= a[i];
}
score = Math.pow(muti, 1.0/n);
return score;
}
}
/**
* 策略三
* 計算去掉最高分最低分以後的代數平均分
*/
public class StrategyThree implements ComputableStrategy{
@Override
public double computeScore(double[] a) {
if (a.length <= 0) {
return 0;
}
double score = 0;
double sum = 0;
Arrays.sort(a);
for (int i = 1; i < a.length-1; i++) {
sum += a[i];
}
score = sum / (a.length - 2);
return score;
}
}
/**
* 啓動器類
*/
public class Application {
public static void main(String[] args) {
GymnasticsGame game = new GymnasticsGame(); //上下文對象
game.setStrategy(new StrategyOne()); //上下文使用策略一
Person zhang = new Person();
zhang.setName("張三");
double[] a = {9.12,9.25,8.87,9.81,8.32,7.88};
Person li = new Person();
li.setName("李四");
double[] b = {8.12,9.25,8.17,9.81,9.32,7.28};
zhang.setScore(game.getPersonScore(a));
li.setScore(game.getPersonScore(b));
System.out.println("使用算術平均值方案:");
System.out.printf("%s 最後得分:%5.3f %n",zhang.getName(),zhang.getScore());
System.out.printf("%s 最後得分:%5.3f %n",li.getName(),li.getScore());
game.setStrategy(new StrategyTwo()); //上下文使用策略二
zhang.setScore(game.getPersonScore(a));
li.setScore(game.getPersonScore(b));
System.out.println("*******************");
System.out.println("使用幾何平均值方案:");
System.out.printf("%s 最後得分:%5.3f %n",zhang.getName(),zhang.getScore());
System.out.printf("%s 最後得分:%5.3f %n",li.getName(),li.getScore());
System.out.println("*******************");
game.setStrategy(new StrategyThree()); //上下文使用策略三
zhang.setScore(game.getPersonScore(a));
li.setScore(game.getPersonScore(b));
System.out.println("使用(去掉最高,最低)算術平均值方案:");
System.out.printf("%s 最後得分:%5.3f %n",zhang.getName(),zhang.getScore());
System.out.printf("%s 最後得分:%5.3f %n",li.getName(),li.getScore());
}
}
最後運行結果: