設計模式 - Strategy - 策略模式

Strategy模式:

  • 策略模式,我們可以把策略理解爲算法,而策略模式就是我們將一個策略的實現委託給一個接口的實現類去實現,當我們只要更換實現類就實現了策略的更換的目的,比如遊戲中的難度切換,也可以說是把AI接口的實現類切換了。

實例:

  • 模擬兩個選手猜拳,爲了勝利,兩個選手選擇不同的策略,這裏兩個策略,一個是這次贏了,下次還做出同樣的選擇,如果輸了就隨機出拳,而另一個則是,記錄下自己兩次出拳的勝利記錄,通過當前出拳,根據記錄來做出下次出拳贏面最大的選擇,這裏採用的是吧下次三種拳加起來,生成隨機數,看它落在那個區域,贏面大的區域大,被選中的概率也就大。

Hand 類:

package com.zyy.pattern.beans;


public class Hand {
	private int handValue;
	public Hand(int handValue) {
		this.handValue = handValue;
	}
	
	
	
	public int getHandValue() {
		return handValue;
	}



	public static final Hand[] HANDS = new Hand[]{
			new Hand(0),
			new Hand(1),
			new Hand(2)
	};
	
	public static final String[] STRINGS = new String[] {
			"石頭",
			"剪刀",
			"布"
	};
	
	public static Hand getHand(int handValue) {
		return HANDS[handValue];
	}
	
	public boolean isStrongerThan(Hand h) {
		return  fight(h) == 1;
	}
	
	public boolean isEqual(Hand h) {
		return fight(h) == 0;
	}
	
	public boolean isWeakerThan(Hand h) {
		return fight(h) == -1;
	}
	public int fight(Hand h) {
		if(this.getHandValue() == h.getHandValue()) {
			return 0;
		} else if((this.getHandValue() + 1) % 3 == h.getHandValue()) {
			return 1;
		}else {
			return -1;
		}
	}
}

Strategy 接口:

package com.zyy.pattern.service;

import com.zyy.pattern.beans.Hand;

public interface Strategy {
	Hand nextHand();
	void study(boolean win);
}

WinningStrategy 類:

package com.zyy.pattern.beans;

import java.util.Random;

import com.zyy.pattern.service.Strategy;

public class WinningStrategy implements Strategy{
	private Random random;
	private boolean won = false;
	private Hand prevHand;
	public WinningStrategy(long seed) {
		random = new Random(seed);
	}

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

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

}

ProbStrategy 類:

package com.zyy.pattern.beans;


import java.util.Random;

import com.zyy.pattern.service.Strategy;

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(long seed) {
		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;
		}
		return Hand.getHand(handValue);
	}
	
	private int getSum(int currentHandValue) {
		int sum = 0;
		for(int i = 0;i < 3;i++) {
			sum += history[currentHandValue][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 類:

package com.zyy.pattern.beans;

import com.zyy.pattern.service.Strategy;

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
			+ "]";
}
 
 
}

測試實例以及測試結果:

public void StrategyPatternTest() {
		long seedFirst = 1;
		long seedSecond = 2;
		Player playerFirst = new Player("ke", new WinningStrategy(1));
		Player playerSecond = new Player("liang", new ProbStrategy(2));
		for(int i =0 ; i < 1000;i++) {
			Hand nextHandFirst = playerFirst.nextHand();
			Hand nextHandSecond = playerSecond.nextHand();
			logger.info("firstIsNull : {}",nextHandFirst == null);
			logger.info("secondIsNull : {}",nextHandSecond == null);
			if(nextHandFirst.isStrongerThan(nextHandSecond)) {
				logger.info("winner : {}",playerFirst);
				playerFirst.win();
				playerSecond.lose();
			}else if(nextHandFirst.isWeakerThan(nextHandSecond)) {
				logger.info("winner : {}",playerSecond);
				playerFirst.lose();
				playerSecond.win();
			}else {
				playerFirst.even();
				playerSecond.even();
			}
		}
		logger.info("playerFirst : {}",playerFirst);
		logger.info("playerSecond : {}",playerSecond);
	}
	
	
	21:53:59.739 [main] INFO testSpringFirst.DesignPatternTest - playerFirst : Player [name=ke, winCount=327, loseCount=336, gameCount=1000]
21:53:59.739 [main] INFO testSpringFirst.DesignPatternTest - playerSecond : Player [name=liang, winCount=336, loseCount=327, gameCount=1000]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章