实现背景
策略(strategy)模式,无论什么程序,其目的都是解决问题。而面对不同的问题,可能就会有不同的解决方法,strategy模式可以整体地替换算法的实现部分。能够整体地替换算法,能让我们轻松地以不同的方法去解决同一个问题。
登场角色
Strategy(策略)
Strategy 角色负责决定实现策略所必须的接口(API)
ConcreteStrategy(具体的策略)
角色负责实现Strategy的接口,即负责实现具体的策略
Context(上下文)
负责使用 Strategy 角色
类图
实例代码
以石头剪刀布作为例子,玩家在每次出石头剪刀布时都有不同的策略
手势类
public class Hand {
public static final int HANDVALUE_GUU = 0; // 石头的值
public static final int HANDVALUE_CHO = 1; // 剪刀的值
public static final int HANDVALUE_PAA = 2; // 布的值
private int handValue;
public Hand(int handValue) {
this.handValue = handValue;
}
/**
* 使用 单例模式 获取这三个中的值
*/
public static final Hand[] hands = {
new Hand(HANDVALUE_GUU),
new Hand(HANDVALUE_CHO),
new Hand(HANDVALUE_PAA)
};
private static final String[] handNames = {"石头", "剪刀", "布"};
/**
* 获取 hand的值
*
* @param handValue
* @return
*/
public static Hand getHand(int handValue) {
return hands[handValue];
}
/**
* 获取hand的名称
*
* @param handValue
* @return
*/
public String getHandName(int handValue) {
return handNames[handValue];
}
/**
* 比赢了
* @param hand
* @return
*/
public boolean isStrongThanOther(Hand hand) {
return fight(hand) == 1;
}
/**
* 比输了
* @param hand
* @return
*/
public boolean isWorseThanOther(Hand hand) {
return fight(hand) == -1;
}
/**
* 比较
* @param hand
* @return
*/
private int fight(Hand hand) {
if (this == hand) {
// 平手
return 0;
} else if ((this.handValue + 1) % 3 == hand.handValue) {
return 1;
} else {
return -1;
}
}
}
Strategy接口
/**
* 定义策略的接口
*/
public interface Strategy {
// 获取下一局所要出的手势
Hand nextHand();
// 学习上一局是否赢了
void study(boolean win);
}
WinningStrategy类:若赢了,下次出的手势与上次一样
import java.util.Random;
public class WinningStrategy implements Strategy{
private Random random;
// 上一局是否赢了
private boolean won = false;
// 上一局的结果
private Hand preHand;
public WinningStrategy(int seed) {
this.random = new Random(seed);
}
@Override
public Hand nextHand() {
if (!won) {
preHand = Hand.getHand(random.nextInt(3));
}
return preHand;
}
@Override
public void study(boolean win) {
won = win;
}
}
ProbStrategy类:根据以往的出拳的概率判断下一次所出的手势
public class ProbStrategy implements Strategy {
private Random random;
private int currentHandValue = 0;
private int preHandValue = 0;
public ProbStrategy(int seed) {
this.random = new Random(seed);
}
/**
* history[上一局所出的手势][这一局所出的手势]
*/
private int[][] history = {
{1, 1, 1},
{1, 1, 1},
{1, 1, 1}
};
@Override
public Hand nextHand() {
int handValue = 0;
int bet = random.nextInt(getSum(currentHandValue));
if (bet < history[currentHandValue][0]) {
handValue = 0;
} else if (bet < history[currentHandValue][0] + history[currentHandValue][1]) {
handValue = 1;
} else {
handValue = 2;
}
preHandValue = currentHandValue;
currentHandValue = handValue;
return Hand.getHand(handValue);
}
@Override
public void study(boolean win) {
if (win) {
history[preHandValue][currentHandValue]++;
} else {
history[preHandValue][(currentHandValue + 1) % 3]++;
history[preHandValue][(currentHandValue + 2) % 3]++;
}
}
private int getSum(int hv) {
int sum = 0;
for (int i = 0; i < 3; i++) {
sum += history[hv][i];
}
return sum;
}
}
Player类:相当于 Context
public class Player {
private String name;
private Strategy strategy;
private int winTimes;
private int loseTimes;
private int gameTimes;
public Player(String name, Strategy strategy) {
this.name = name;
this.strategy = strategy;
}
public Hand nextHand() {
return strategy.nextHand();
}
public void win() { // 胜
strategy.study(true);
winTimes++;
gameTimes++;
}
public void lose() { // 负
strategy.study(false);
loseTimes++;
gameTimes++;
}
public void even() { // 平
gameTimes++;
}
@Override
public String toString() {
return "Player{" +
"name='" + name + ''' +
", strategy=" + strategy +
", winTimes=" + winTimes +
", loseTimes=" + loseTimes +
", gameTimes=" + gameTimes +
'}';
}
}
Main类
public class Main {
public static void main(String[] args) {
int seed1 = 2;
int seed2 = 3;
Player player1 = new Player("Taro", new WinningStrategy(seed1));
Player player2 = new Player("Hana", new ProbStrategy(seed2));
for (int i = 0; i < 10000; i++) {
Hand hand1 = player1.nextHand();
Hand hand2 = player2.nextHand();
if (hand1.isStrongThanOther(hand2)) {
System.out.println("Winner is " + player1);
player1.win();
player2.lose();
} else if (hand2.isStrongThanOther(hand1)) {
System.out.println("Winner is " + 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());
}
}