设计模式(Java)—Strategy模式

以不同的算法去解决同一个问题的模式是Strategy模式,Strategy模式可以整体地替换算法的实现部分。

一、示例程序
“猜拳游戏”
两种策略:1.如果这局猜拳获胜,那么下一局也出一样手势;2.根据上一局的手势从概率上计算出下一局的手势
在这里插入图片描述

Hand类:

package Strategy;

public class Hand {
	//表示石头、剪刀、布三个的值
	public static final int HANDVALUE_GUU = 0;
	public static final int HANDVALUE_CHO = 1;
	public static final int HANDVALUE_PAA = 2;
	//初始时创建数组,使用单例模式
	public static final Hand[] hand = {
			new Hand(HANDVALUE_GUU),
			new Hand(HANDVALUE_CHO),
			new Hand(HANDVALUE_PAA),			
	};
	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 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];
	}
}

Hand类表示猜拳游戏中的手势的类,在该类的内部,0-石头、1-剪刀、2-布
开始时创建三个实例,包括石头剪刀布三个实例,保存在数组中。判断猜拳结果的是isStrongThan方法和isWeakThan方法,实际负责判断猜拳结果的是fight方法。

Strategy接口:

package Strategy;

//算法接口,抽象方法,在实现该接口的类中必须实现这些方法
public interface Strategy {
	public abstract Hand nextHand();
	public abstract void study(boolean win);
}

该接口定义了猜拳策略的抽象方法,nextHand方法的作用是获取下一局要出的手势,study方法是学习上一局是否胜利了,如果调用了nextHand方法获胜了就调用study(true),如果失败了就调用study(false)

WinningStrategy类:

package Strategy;

import java.util.Random;

//实现抽象接口的具体类
public class WinningStrategy implements Strategy {
	private Random random;
	private boolean won = false;
	private Hand prevHand;
	//初始时随机
	public WinningStrategy(int seed) {
		// TODO Auto-generated constructor stub
		random = new Random(seed);
	}
	//如果上一局输了,则这句随机出,如果赢了,继续出上一句的策略
	@Override
	public Hand nextHand() {
		// TODO Auto-generated method stub
		if(!won){
			prevHand = Hand.getHand(random.nextInt(3));
		}
		return prevHand;
	}
    //获取上一局是赢了还是输了
	@Override
	public void study(boolean win) {
		// TODO Auto-generated method stub
		won = win;

	}

}

接口的实现类,won字段保留上一局的结果,prevHand保留上一局的手势

ProbStrategy类

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(win){
			history[prevHandValue][currentHandValue]++;
		}else{
			history[prevHandValue][(currentHandValue+1)%3]++;
			history[prevHandValue][(currentHandValue+2)%3]++;
		}

	}

}

另外一个具体的策略类
在这里插入图片描述

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;
	}
	//委托实现使用策略
	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 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());

	}

}

在这里插入图片描述

注:使用委托这种弱关联关系可以很方便的替换整个算法。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值