The pattern to solve the same problem with different algorithms is Strategy pattern, which can replace the implementation part of the algorithm as a whole.
1, Sample program
"Guessing game"
There are two strategies: 1. If this round of guessing is successful, the next round will show the same gesture; 2. Calculate the next round's gesture from the probability according to the previous round's gesture
Class Hand:
package Strategy; public class Hand { //The value of stone, scissors and cloth public static final int HANDVALUE_GUU = 0; public static final int HANDVALUE_CHO = 1; public static final int HANDVALUE_PAA = 2; //Create array initially, using singleton mode public static final Hand[] hand = { new Hand(HANDVALUE_GUU), new Hand(HANDVALUE_CHO), new Hand(HANDVALUE_PAA), }; private static final String[] name = { "stone","scissors","cloth", }; private int handvalue; private Hand(int handvalue){ this.handvalue = handvalue; } //Get the current sale value public static Hand getHand(int handvalue){ return hand[handvalue]; } public boolean isStrongThan(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]; } }
The Hand class represents the gesture class in the guessing game. Inside the class, 0-stone, 1-scissors, 2-cloth
At the beginning, three instances are created, including three instances of stone scissor cloth, which are saved in the array. The isStrongThan method and isWeakThan method are used to judge the result of guessing boxing, while the fight method is actually used to judge the result of guessing boxing.
Strategy interface:
package Strategy; //Algorithmic interfaces, abstract methods, which must be implemented in the class implementing the interface public interface Strategy { public abstract Hand nextHand(); public abstract void study(boolean win); }
This interface defines the abstract method of guessing boxing strategy. The function of nextHand method is to get the next round of gestures. Study method is to learn whether the previous round has won. If nextHand method is called, study(true) will be called. If it fails, study(false) will be called
WinningStrategy class:
package Strategy; import java.util.Random; //Concrete classes that implement abstract interfaces public class WinningStrategy implements Strategy { private Random random; private boolean won = false; private Hand prevHand; //Initially random public WinningStrategy(int seed) { // TODO Auto-generated constructor stub random = new Random(seed); } //If you lose in the last game, the sentence will go out randomly. If you win, continue the strategy of the previous sentence @Override public Hand nextHand() { // TODO Auto-generated method stub if(!won){ prevHand = Hand.getHand(random.nextInt(3)); } return prevHand; } //Win or lose the last game @Override public void study(boolean win) { // TODO Auto-generated method stub won = win; } }
The implementation class of the interface, the won field keeps the result of the previous round, and prevHand keeps the gesture of the previous round
ProbStrategy class
package Strategy; 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) { // TODO Auto-generated constructor stub random = new Random(seed); } @Override public Hand nextHand() { // TODO Auto-generated method stub 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) { // TODO Auto-generated method stub int sum = 0; for(int i = 0;i<3;i++){ sum += history[hv][i]; } return sum; } @Override public void study(boolean win) { // TODO Auto-generated method stub //If you win the current algorithm weight increase, if you lose another algorithm weight increase if(win){ history[prevHandValue][currentHandValue]++; }else{ history[prevHandValue][(currentHandValue+1)%3]++; history[prevHandValue][(currentHandValue+2)%3]++; } } }
Another specific strategy class
Class Player:
package 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; } //Delegate implementation usage policy 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"+"]"; } }
Class Main:
package Strategy; public class Main { public static void main(String[] args) { // TODO Auto-generated method stub 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 WinningStrategy(seed2)); for (int i = 0; i<1000;i++){ Hand nextHand1 = player1.nextHand(); Hand nextHand2 = player2.nextHand(); if(nextHand1.isStrongThan(nextHand2)) { System.out.println("Winner:"+player1); player1.win(); player2.lose(); }else if(nextHand1.isWeakerThan(nextHand2)){ System.out.println("Winner:"+player2); player2.win(); player1.lose(); }else{ System.out.println("Even..."); player1.even(); player2.even(); } try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println("Total result:"); System.out.println(player1.toString()); System.out.println(player2.toString()); } }
Note: it is convenient to replace the whole algorithm with delegation.