情景引入
在本章中,我们将要学习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; } else { return -1; } }
@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());
} } } }
|