Strategy模式

情景引入

在本章中,我们将要学习Strategy模式。

Strategy的意思是“策略”,指的是与敌军对垒时行军作战的方法。在编程中,我们可以将它理
解为“算法”。

无论什么程序,其目的都是解决问题。而为了解决问题,我们又需要编写特定的算法。使用
Strategy模式可以整体地替换算法的实现部分。能够整体地替换算法,能让我们轻松地以不同的算
法去解决-一个问题,这种模式就是Strategy模式。

针对于同一事件的不同情况给出不同解决方案

示例程序

功能描述

让电脑玩猜拳游戏

类的一览表

名字 说明
Hand 表示猜拳游戏中的“手势”的类
Strategy 表示猜拳游戏中的策略的接口
WinningStrategy 表示“如果这局猜拳获胜,那么下一局也出一样的手势”这一策略的类
ProbStrategy 表示“根据上一局的手势从概率上计算出下一局的手势从之前的猜拳结果计算下一局出各种拳的概率”这一策略的类
Player 表示进行猜拳游戏的选手的类
Main 测试程序行为的类

UML

策略模式

主要代码

Hand 类

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
46
public class Hand {
public static final int HAND_VALUE_GUU = 0; // 表示石头的值
public static final int HAND_VALUE_CUO = 1; // 表示剪刀的值
public static final int HAND_VALUE_PAA = 2; // 表示布的值
public static final Hand[] hand = {
new Hand(HAND_VALUE_GUU),
new Hand(HAND_VALUE_CUO),
new Hand(HAND_VALUE_PAA),
};

private static final String[] name = {
"石头", "剪刀", "布"
};
private int handValue;

private Hand(int handValue) {
this.handValue = handValue;
}

public static Hand getHand(int handValue) {
return hand[handValue];
}

public boolean isStrongerThan(Hand h) {
return this.fight(h) == 1;
}

public boolean isWeakerThan(Hand h) {
return this.fight(h) == -1;
}

private int fight(Hand h) {
if (this == h) {// 平
return 0;
} else if ((this.handValue + 1) % 3 == h.handValue) {
return 1; // this 胜
} else {
return -1; // this 负
}
}

@Override
public String toString() {
return name[handValue];
}
}

Strategy 类

1
2
3
4
public interface Strategy {
Hand nextHand();
void study(boolean win);
}

WinningStrategy 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class WinningStrategy implements Strategy{
private Random random;
private boolean won = false;
private Hand prevHand;

public WinningStrategy(int seed) {
this.random = new Random(seed);
}

@Override
public Hand nextHand() {
if (!won){
return prevHand = Hand.getHand(random.nextInt(3));
}
return prevHand;
}

@Override
public void study(boolean win) {
won = win;
}
}

ProbStrategy 类

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
46
47
48
public class ProbStrategy implements Strategy {
private Random random;
private int prevHandValue = 0;
private int currentHandValue = 0;
private int[][] history = {
{1, 1, 1},
{1, 1, 1},
{1, 1, 1},
};

public ProbStrategy(int seed) {
this.random = new Random(seed);
}

@Override
public Hand nextHand() {
int bet = random.nextInt(getSum(currentHandValue));
int handValue = 0;
if (bet < history[currentHandValue][0]){
handValue = 0;
}else if (bet < history[currentHandValue][0] + history[currentHandValue][1]){
handValue = 1;
}else{
handValue = 2;
}
prevHandValue = currentHandValue;
currentHandValue = handValue;
return Hand.getHand(handValue);
}

private int getSum(int hv) {
int sum = 0;
for (int i = 0; i < 3; i++) {
sum += history[hv][i];
}
return sum;
}

@Override
public void study(boolean win) {
if (win) {
history[prevHandValue][currentHandValue]++;
} else {
history[prevHandValue][(currentHandValue + 1) % 3]++;
history[prevHandValue][(currentHandValue + 2) % 3]++;
}
}
}

Player 类

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
public class Player {
private String name;
private Strategy strategy;
private int wincount;
private int losecount;
private int gamecount;

public Player(String name, Strategy strategy) {
this.name = name;
this.strategy = strategy;
}
public Hand nextHand(){
return strategy.nextHand();
}
public void win(){
strategy.study(true);
wincount++;
gamecount++;
}
public void lose(){
strategy.study(false);
losecount++;
gamecount++;
}
public void even(){
gamecount++;
}

@Override
public String toString() {
return "Player{" +
"name='" + name + '\'' +
", wincount=" + wincount +
", losecount=" + losecount +
", gamecount=" + gamecount +
'}';
}
}

Main 类

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
public class Main {
public static void main(String[] args) {
if (args.length != 2) {
System.out.println("Usage: java Main randomseed1 randomseed2");
System.out.println("Example: java Main 314 15");
System.exit(0);
int seed1 = Integer.parseInt(args[0]);
int seed2 = Integer.parseInt(args[1]);
Player player1 = new Player("Taro", new WinningStrategy(seed1));
Player player2 = new Player("Hana",
new ProbStrategy(seed2));
for (int i = 0; i < 10000; i++) {
Hand nextHand1 = player1.nextHand();
Hand nextHand2 = player2.nextHand();
if (nextHand1.isStrongerThan(nextHand2)) {
System.out.println("Winner:" + player1);
player1.win();
player2.lose();
} else if (nextHand2.isStrongerThan(nextHand1)) {
System.out.println("Winner:" + player2);
player1.lose();
player2.win();
} else{
System.out.println("Even...");
player1.even();
player2.even();
}
System.out.println("Total result:");
System.out.println(player1.toString());
System.out.println(player2.toString());

}
}
}
}

Strategy模式
http://lhystutest.top/2022/11/01/设计模式/Strategy 模式/Strategy模式/
作者
lhy
发布于
2022年11月1日
许可协议