# 设计模式（十）-策略模式（Strategy Pattern）——整体的替换算法

Hand.java

package com.test.dp.Strategy.Sample;

//算法需要计算的对象，这里代表“手势”
public class Hand {
public static final int HANDVALUE_GUU = 0;  // 表示石头的值
public static final int HANDVALUE_CHO = 1;  // 表示剪刀的值
public static final int HANDVALUE_PAA = 2;  // 表示布的值
public static final Hand[] hand = {         // 表示猜拳中3种手势的实例
new Hand(HANDVALUE_GUU),
new Hand(HANDVALUE_CHO),
new Hand(HANDVALUE_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) {     // 如果this胜了h则返回true
return fight(h) == 1;
}
public boolean isWeakerThan(Hand h) {       // 如果this输给了h则返回true
return fight(h) == -1;
}
private int fight(Hand h) {                 // 计分：平0, 胜1, 负-1
if (this == h) {
return 0;
} else if ((this.handvalue + 1) % 3 == h.handvalue) {
return 1;
} else {
return -1;
}
}
public String toString() {                  // 转换为手势值所对应的字符串
return name[handvalue];
}
}

Strategy.java

package com.test.dp.Strategy.Sample;

//策略抽象类
public interface Strategy {
public abstract Hand nextHand();
public abstract void study(boolean win);
}

WinningStrategy.java

package com.test.dp.Strategy.Sample;

import java.util.Random;

//策略算法实现：根据上一局的手势从概率上计算出下一局的手势从之前的猜拳结果计算下一局各种拳的概率
public class WinningStrategy implements Strategy {
private Random random;
private boolean won = false;
private Hand prevHand;
public WinningStrategy(int seed) {
random = new Random(seed);
}
public Hand nextHand() {
if (!won) {
prevHand = Hand.getHand(random.nextInt(3));
}
return prevHand;
}
public void study(boolean win) {
won = win;
}
}

ProbStrategy.java

package com.test.dp.Strategy.Sample;

import java.util.Random;

//策略算法实现：如果这局猜拳获胜，那么下一局也出一样的手势
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) {
random = new Random(seed);
}
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;
}
public void study(boolean win) {
if (win) {
history[prevHandValue][currentHandValue]++;
} else {
history[prevHandValue][(currentHandValue + 1) % 3]++;
history[prevHandValue][(currentHandValue + 2) % 3]++;
}
}
}

Player.java

package com.test.dp.Strategy.Sample;

//使用策略的对象，这里表示“猜拳玩家”
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++;
}
public String toString() {
return "[" + name + ":" + gamecount + " games, " + wincount + " win, " + losecount + " lose" + "]";
}
}

Main.java

package com.test.dp.Strategy.Sample;

public class Main {
public static void main(String[] args) {
args = new String[]{"5", "6"};
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());
}
}


Winner:[Hana:7679 games, 2645 win, 2432 lose]
Winner:[Hana:7680 games, 2646 win, 2432 lose]
Even...
Even...
Winner:[Taro:7683 games, 2432 win, 2647 lose]
Even...
Winner:[Taro:7685 games, 2433 win, 2647 lose]
Even...
Winner:[Taro:7687 games, 2434 win, 2647 lose]
Even...
Winner:[Taro:7689 games, 2435 win, 2647 lose]
……此处省略若干行
Winner:[Taro:9996 games, 3178 win, 3449 lose]
Winner:[Taro:9997 games, 3179 win, 3449 lose]
Even...
Winner:[Hana:9999 games, 3449 win, 3180 lose]
Total result:
[Taro:10000 games, 3180 win, 3450 lose]
[Hana:10000 games, 3450 win, 3180 lose]

• 本文已收录于以下专栏：

## Java设计模式——策略模式（Strategy Pattern）

Java设计模式——策略模式（Strategy Pattern） 场景一 描述：刘备要到江东娶老婆了，走之前诸葛亮给赵云（伴郎）三个锦囊妙计，说是按天机拆开解决棘手问题，嘿，还别说，真是解决了大问题，...
• u012401711
• 2016年09月07日 21:16
• 1115

本作品采用知识共享署名-非商业性使用-相同方式共享 3.0 Unported许可协议进行许可。允许非商业转载，但应注明作者及出处。 作者：liuyuan_jq2011-06-13 策略模式定义 定...
• liuyuan_jq
• 2011年06月13日 17:41
• 1481

## 浅谈JAVA设计模式之——策略模式（Strategy）

• l1028386804
• 2015年05月09日 14:02
• 1892

## 我所理解的设计模式（C++实现）——策略模式（Strategy Pattern）

• LCL_data
• 2013年08月24日 10:59
• 12929

## 设计模式--深度解析策略模式（Strategy Pattern）

• qq_29282475
• 2015年12月04日 14:17
• 3560

## C++设计模式<四>：策略模式（Strategy）

1.动机在软件构件过程中，某些对象使用的算法可能多种多样，经常改变，如果将这些算法都编码到对象中，将会使对象变得异常复杂；而且有时候支持不使用的算法也是一个性能负担。2.模式定义定义一系列算法，把它们...
• MonroeD
• 2016年04月08日 01:16
• 397

## 设计模式：策略模式（Python）

• ericzhong83
• 2012年05月17日 23:53
• 4904

## 策略模式（Strategy Pattern）就这么简单

0x00 举个生活中的例子某个大人网站是会员制的，金牌会员购买精神食粮打7折，银牌会员打8折，铜牌会员打9折，铁牌会员不打折。也就是说不同的用户在购买精神食粮的时候结算的价格是不一样的，即使你们买相同...
• fiendvip
• 2016年04月12日 21:18
• 4271

## 设计模式 - 策略模式(Strategy Pattern) 详解

• u012515223
• 2014年05月22日 13:31
• 2915

## 设计模式--spring源码中使用策略模式（Strategy Pattern）

• a137268431
• 2016年07月04日 17:32
• 1227

举报原因： 您举报文章：设计模式（十）-策略模式（Strategy Pattern）——整体的替换算法 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)