Strategyパターン クラス図 |
ConcreteStrategy・・・・Strategyクラスの具象クラス。
ここに具体的な戦略・方策・方法・アルゴリズムを実装する。
Context・・・・メンバにstrategyを持ち、必要に応じてStrategyクラスに委譲するためのクラス。
--------------------------------------------------------------------------
サンプルソース
・じゃんけん
--------------------------------------------------------------------------
Strategyにあたるクラス
ファイル名:Strategy.java
public interface Strategy {
public abstract Hand nextHand();
public abstract void study(boolean win);
}
--------------------------------------------------------------------------
ConcreteStrategyにあたるクラス①。
studyメソッドで選択を決め、nextHandメソッドで結果を返す。
WinningStrategyクラス:勝ったら次も同じ手を出す。
ファイル名:WinningStrategy.java
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;
}
}
--------------------------------------------------------------------------
ConcreteStrategyにあたるクラス②。
studyメソッドで選択を決め、nextHandメソッドで結果を返す。
ProbStrategyクラス:1回前の手から次の手を確立をつかって出す。
ファイル名:ProbStrategy.java
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]++;
}
}
}
--------------------------------------------------------------------------
Contextにあたるクラス。
ファイル名:Player.java
public class Player {
private String name;
private Strategy strategy;
private int wincount;
private int losecount;
private int gamecount;
// 渡ってくるConcreteStrategyにより振る舞いが変わる
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クラス。
ファイル名:Main.java
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]);
// Contextにあたるオブジェクトを生成。渡すConcreteStrategyにより振る舞いが変わる。
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());
}
}
0 件のコメント:
コメントを投稿