所有设计模式传送门
定义一系列算法,把他们一个个封装起来,并使它们可以相互的替换。本模式使得算法可独立于使用它的客户而变化。策略模式 也是处理算法不同变体的一种成熟模式。
包含的角色:
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());
}
}
最后运行结果: