1、模式說明java
策略模式比較好理解,就是將程序中用到的算法總體的拿出來,並有多個不一樣版本的算法實現,在程序運行階段,動態的決定使用哪一個算法來解決問題。算法
舉個實際的例子:排序算法的問題,假如咱們的程序中須要對數據進行排序,咱們知道,不一樣的算法具備不一樣的時間複雜度和空間複雜度,所以須要在程序運行時,根據可用內存和數據特徵,選用不一樣的算法(排序策略),這就是策略模式的使用場景之一。再舉個例子,負載均衡算法:若是某個服務部署了多個冗餘的實例,客戶端在向服務端發送請求時,根據負載均衡算法策略,請求可能會被轉發到不一樣的服務提供者實例來處理,如何決定某個請求轉發給哪一個服務實例呢,最簡單的作法就是輪詢,順次將請求轉發給每一個服務實例進行處理。也能夠採用隨機方式,或者根據實際硬件環境和業務場景設置特定算法。設計模式
2、模式類圖負載均衡
3、程序示例dom
在下面的演示策略模式的代碼示例中,咱們模擬猜拳遊戲——剪刀石頭布,猜拳的策略有兩種:若是此次猜拳贏了,則下次還出一樣的手勢。另外一種策略就是根據之前的猜拳結果,選擇勝率最高的一種手勢。ide
一、Hand類:表示猜拳遊戲中的手勢,並不是Strategy策略模式中的角色。this
package com.designpattern.cn.strategypattern; public class Hand { public static final int HANDVALUE_ROCK = 0; //表示石頭 public static final int HANDVALUE_SCISSORS = 1; //表示剪刀 public static final int HANDVALUE_PEPER = 2; //表示布 private static final Hand[] hand = { new Hand(HANDVALUE_ROCK), new Hand(HANDVALUE_SCISSORS), new Hand(HANDVALUE_PEPER) }; 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 fight(h) == 1; } public boolean isWeakerThan(Hand h){ return 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; } } public String toString(){ return name[handValue]; } }
二、Strategy接口:spa
package com.designpattern.cn.strategypattern; public interface Strategy { public abstract Hand nextHand(); public abstract void study(boolean win); }
三、WinningStrategy類:設計
package com.designpattern.cn.strategypattern; 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類:3d
package com.designpattern.cn.strategypattern; import java.util.Random; public class ProbStrategy implements Strategy { private Random random; private int prevHandValue = 0; private int currentHandValue = 0; //history[上一局的手勢][這一局的手勢] 表達式的值越高表示過去的勝率越高 //study方法會根據nextHand方法返回的手勢勝負結果更新history字段中的值 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][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 : history[hv] ) { sum += 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類:
package com.designpattern.cn.strategypattern; 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類與運行結果:
package com.designpattern.cn.strategypattern; import java.util.Random; public class Main { public static void main(String[] args){ int seed1 = ((new Random()).nextInt(500))*(1+(new Random()).nextInt(500)); int seed2 = seed1 * (new Random()).nextInt(500); Player player1 = new Player("Taro", new WinningStrategy(seed1)); Player player2 = new Player("Hana", new ProbStrategy(seed2)); for(int i = 0; i < 100000; 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); player2.win(); player1.lose(); }else{ System.out.println("Even..."); player1.even(); player2.even(); } } System.out.println("Total result:"); System.out.println(player1.toString()); System.out.println(player2.toString()); } }
4、Strategy策略模式中的角色
5、相關的設計模式