Java设计模式--策略模式

策略模式(别名:政策)

定义一系列算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。

Strategy Pattern(Another Name: Policy)

Define a family of algorithms, encapsulate each one, and make them inter changeable. Strategy lets the algorithm vary independently from clients that use it.

类图

模式的结构与使用

策略方法模式的结构中包括三种角色。

  • 策略(Strategy):策略是一个接口,该接口定义若干个算法标识,即定义了若干个抽象方法。
  • 具体策略(Concrete Strategy):具体策略是实现策略接口的类。具体策略实现策略接口所定义的抽象方法,即给出算法标识的具体算法。
  • 上下文(Context):上下文是依赖于策略接口的类,即上下文包含有策略声明的变量。上下文中提供一个方法,该方法委托策略变量调用具体策略所实现的策略接口中的方法。

简单的例子

Abstract Strategy的接口类ComputableStrategy.java

1
2
3
4
5
package Strategy;
public interface ComputableStrategy {
public abstract double computableStrategy(double[] a);
}

Strategy的实现类StrategyOne.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package Strategy;
public class StrategyOne implements ComputableStrategy {
@Override
public double computableStrategy(double[] a) {
double score = 0, sum = 0;
for (int i = 0; i < a.length; i++) {
sum = sum + a[i];
}
score = sum/a.length;
return score;
}
}

Strategy的实现类StrategyTwo.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package Strategy;
public class StrategyTwo implements ComputableStrategy {
@Override
public double computableStrategy(double[] a) {
double score = 0, multi = 1;
int n = a.length;
for (int i = 0; i < a.length; i++) {
multi = multi * a[i];
}
score = Math.pow(multi, 1.0/n);
return score;
}
}

Strategy的实现类StrategyThree.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package Strategy;
import java.util.Arrays;
public class StrategyThree implements ComputableStrategy {
@Override
public double computableStrategy(double[] a) {
if (a.length <= 2)
return 0;
double score = 0, sum = 0;
Arrays.sort(a);
for (int i = 1; i < a.length - 1; i++) {
sum = sum + a[i];
}
score = sum/(a.length-2);
return score;
}
}

Context类GymnasticsGame.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package Strategy;
public class GymnasticsGame {
ComputableStrategy strategy;
public void setStrategy(ComputableStrategy strategy) {
this.strategy = strategy;
}
public double getPersonScore(double a[]) {
if (strategy != null) {
return strategy.computableStrategy(a);
} else
return 0;
}
}

测试类Application.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package Strategy;
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.99, 6.99, 7.88};
Person li = new Person();
li.setName("李四");
zhang.setScore(game.getPersonScore(a));
li.setScore(game.getPersonScore(a));
System.out.println(zhang.getScore());
System.out.println(li.getScore());
game.setStrategy(new StrategyThree());
zhang.setScore(game.getPersonScore(a));
li.setScore(game.getPersonScore(a));
System.out.println(zhang.getScore());
System.out.println(li.getScore());
}
}
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;
}
}

执行效果图

策略模式的优点

  • 上下文(Context)和具体策略(ConcreteStrategy)是松耦合关系。因此上下文只知道它要使用某一个实现Strategy接口类的实例,但不需要知道具体是哪一个类。
  • 策略模式满足“开-闭原则”。当增加新的具体策略时,不需要修改上下文类的代码,上下文就可以引用新的具体策略的实例。

适用策略模式的情景

  • 一个类定义了多种行为,并且这些行为在这个类的方法中以多个条件语句的形式出现,那么可以使用策略模式避免在类中使用大量的条件语句。
  • 程序不希望暴露复杂的、与算法有关的数据结构,那么可以使用策略模式封装算法。
  • 需要使用一个算法的不同变体。

下载源码请到

MyGitHub

文章目录
  1. 1. 策略模式(别名:政策)
  2. 2. Strategy Pattern(Another Name: Policy)
  3. 3. 类图
  4. 4. 模式的结构与使用
  5. 5. 简单的例子
    1. 5.1. Abstract Strategy的接口类ComputableStrategy.java
    2. 5.2. Strategy的实现类StrategyOne.java
    3. 5.3. Strategy的实现类StrategyTwo.java
    4. 5.4. Strategy的实现类StrategyThree.java
    5. 5.5. Context类GymnasticsGame.java
    6. 5.6. 测试类Application.java
  6. 6. 执行效果图
  7. 7. 策略模式的优点
  8. 8. 适用策略模式的情景
  9. 9. 下载源码请到