Design pattern (Java) - Strategy pattern

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.

Keywords: Java

Added by sridhar golyandla on Mon, 30 Dec 2019 23:17:35 +0200