23种设计模式----策略模式----行为型模式

策略模式

  • 1.什么是策略模式
  • 2.角色
  • 3.例子–骰子-大小–猜大小
    • 3.1骰子–实体
    • 3.2策略
    • 3.3乘胜追击–具体的策略
    • 3.4 反其道而行
    • 3.5统计规律
    • 3.6玩家
    • 3.7庄家(mian类)
    • 3.8 1个骰子,100局,哪个策略胜率大
    • 3.9 10个骰子,100000局
    • 3.10 1000个骰子,10 0000 局
  • 4.总结

23种设计模式

1.什么是策略模式

首先,什么策略:策略是与敌军作战的方法,慢慢扩展为做事情的方式;在编程中,可以理解为“算法”。
那么,在编程中,要实现同一个需求,有不同的算法来实现,这些算法有好有坏,而且不同的算法有不同的特点。所以,如果程序根据需要,动态的切换算法,实现功能就比较完善。
策略模式就是为了解决整体的替换算法的这一问题。
策略模式的核心:
委托,模板方法。
使用模板方法达到不同的实现,使用委托达到不同的实例替换。

2.角色

抽象策略—Strategy
具体的策略—StrategyImpl
策略的使用—play

关联
实现
实现 play Strategy Strategy1 Strategy2

3.例子–骰子-大小–猜大小

说起骰子,最简单的就是猜大小的游戏。也是被认为最公平的游戏(不是吗,本例就来验证)
说起玩骰子,几乎每个人都玩过,也都会玩:

要玩骰子,需要一些条件:
骰子、庄家、玩家

3.1骰子–实体

import java.util.Random;

/**
 * 骰子实体
 * 作为骰子,一定是一局游戏中使用同一副骰子
 * 所以,把骰子设计为单例模式
 */
public class Dice {

	//骰子个数
	private static Integer number;
	
	//使用类加载时创建实例,饿汉式。
	private static final Dice DICE = new Dice(); 

	public static Dice getInstance(){
		return DICE;
	}
	
	private Dice(){
	}
	
	public static Integer getDice(){
		if(number != null)
			return new Random().nextInt(number*6);
		else{
			System.out.println("please input the Dice number");
			return null;
		}
	}

	public static Integer getNumber() {
		return number;
	}

	public static void setNumber(Integer number) {
		Dice.number = number;
	}
	
}

3.2策略

想要赢是需要动脑子的

/**
 * 策略接口
 * 1.给出点数
 * 2.设置输赢
 */
public interface Strategy {

	/**
	 * 玩的是压大小的游戏
	 * 所以0 == 小
	 *  1 == 大
	 */
	public Integer getCount();
	
	/**
	 * true表示赢
	 * false表示输
	 */
	public void setWin(Integer integer);
	
}

3.3乘胜追击–具体的策略

乘胜追击–上一把骰子的结果是大,我就压大,上一把骰子结果是小,我就压小。

/**
 * 乘胜追击
 * 策略:上一局的点数作为本次压的点数
 * (与胜负无关)
 */
public class FollowWin implements Strategy{

	//上一局的点数
	private Integer lastNumber = 0;
	
	public Integer getLastWinNumber() {
		return lastNumber;
	}

	public void setLastWinNumber(Integer lastWinNumber) {
		this.lastNumber = lastWinNumber;
	}

	@Override
	public Integer getCount() {
		return lastNumber;
	}

	@Override
	public void setWin(Integer integer) {
		
	}

}

3.4 反其道而行

上一把骰子结果为大,这把我就压小;上一把骰子结果为小,这把我就压大。

/**
 * 反其道而行,上一局相反的点数作为本局压的点数
 * (与胜负无关)
 */
public class OppositeWin implements Strategy{

	private Integer lastNumber = 0;
	
	private Integer num;
	
	public OppositeWin(Integer num){
		this.num = num;
	}
	
	public Integer getLastNumber() {
		return lastNumber;
	}

	public void setLastNumber(Integer lastNumber) {
		this.lastNumber = lastNumber;
	}

	@Override
	public Integer getCount() {
		return 6*num + 1 - lastNumber;
	}

	@Override
	public void setWin(Integer integer) {
		
	}

}

3.5统计规律

哪个点数出现的最多,我压哪个点数(这个点数可能为大,也可能为小)

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 热点数
 * 哪一个点数出现的次数最多,下一局使用哪个点数
 *
 */
public class HotWin implements Strategy{

	//需要初始化map
	private Map<Integer, Integer> map = new HashMap<Integer, Integer>();
	
	public HotWin(Integer num) {
		
		initMap(num);
	}

	private Integer getMax(){
		Integer maxKey = null;
		Integer maxValue = null;
		Iterator<Integer> iterator = map.keySet().iterator();
		while(iterator.hasNext()){
			Integer s = iterator.next();
			if(maxKey == null || maxValue == null){
				maxKey = s;
				maxValue = map.get(s);
			}else if(maxValue < map.get(s)){
				maxKey = s;
				maxValue = map.get(s);
			}
		}
		return maxKey;
	}
	
	private void initMap(Integer num){
		for(Integer i = 1;i <= num*6;i++){
			map.put(i, 0);
		}
	}
	
	@Override
	public Integer getCount() {
		return getMax();
	}

	@Override
	public void setWin(Integer integer) {
		Integer tmp = map.get(integer);
		map.remove(integer);
		map.put(integer, ++tmp);
	}

}

3.6玩家

/**
 * 游戏者
 * 1.压大小
 * 2.获取点数,知晓输赢
 * 3.知道现在是几个骰子
 */
public class Player {

	private String name;
	
	private Strategy strategy;
	
	private Integer num;
	
	private Integer win = 0;
	
	private Integer lose = 0;
	
	public Player(Strategy strategy,Integer num,String name){
		this.strategy = strategy;
		this.num = num;
		this.name = name;
	}
	
	public String getStrategy(){
		return strategy.getClass().getName();
	}
	
	/**
	 * 返回true表示压小
	 * false表示压大
	 * @return
	 */
	public Boolean getBoolean(){
		return strategy.getCount() <= 3*num ;
	}
	
	public void setWin(Integer dice,Boolean bool){
		//bool表示游戏结果(大还是小)
		if(bool == getBoolean()){
			strategy.setWin(dice);
			win++;
		}else{
			strategy.setWin(dice);
			lose++;
		}
	}

	public Integer getNum() {
		return num;
	}

	public Integer getWin() {
		return win;
	}

	public Integer getLose() {
		return lose;
	}

	public String getName() {
		return name;
	}

}

3.7庄家(mian类)

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		
		Scanner scanner = new Scanner(System.in);
		System.out.println("骰子个数");
		int diceCount = scanner.nextInt();
		System.out.println("游戏局数");
		long gameCount = scanner.nextLong();
		//1.获取骰子实例,1个骰子
		Dice.setNumber(diceCount);
		
		//2.初始化游戏者
		Player xiaoming = new Player(new FollowWin(), diceCount,"小明");
		Player xiaohu = new Player(new OppositeWin(diceCount), diceCount, "小虎");
		Player redian = new Player(new HotWin(diceCount), diceCount, "热点");
		
		//3.进行游戏
		long nowCount = 1;
		while(nowCount <= gameCount){
			System.out.println("现在是第"+nowCount+"场游戏");
			System.out.println(xiaoming.getName()+"\t压\t"+(xiaoming.getBoolean()?"小":"大"));
			System.out.println(xiaohu.getName()+"\t压\t"+(xiaohu.getBoolean()?"小":"大"));
			System.out.println(redian.getName()+"\t压\t"+(redian.getBoolean()?"小":"大"));
			Integer number = Dice.getDice()+1;
			System.out.println("点数是"+number+"点");
			Boolean bool = number <= Dice.getNumber()*3;
			System.out.println("结果是\t" + (bool ? "小":"大"));
			
			//通知游戏者本局的点数和结果
			xiaoming.setWin(number, bool);
			xiaohu.setWin(number, bool);
			redian.setWin(number, bool);
			nowCount++;
		}
		
		//4.输出汇总
		System.out.println("总共"+gameCount+"局游戏");
		System.out.println();
		collect(xiaoming);
		System.out.println();
		collect(xiaohu);
		System.out.println();
		collect(redian);
		
		
	}

	private static void collect(Player player){
		System.out.println("我是"+player.getName());
		System.out.println("我赢了"+player.getWin()+"局");
		System.out.println("我输了"+player.getLose()+"局");
		System.out.println("我使用的是"+player.getStrategy()+"策略");
	}
}

3.8 1个骰子,100局,哪个策略胜率大

后面省略过程,只输出结果(循环内的输出注释掉即可)
结尾传送门

骰子个数
1
游戏局数
100
现在是第1场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是4点
结果是	大
现在是第2场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是2点
结果是	小
现在是第3场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是6点
结果是	大
现在是第4场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是5点
结果是	大
现在是第5场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是5点
结果是	大
现在是第6场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是4点
结果是	大
现在是第7场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是3点
结果是	小
现在是第8场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是6点
结果是	大
现在是第9场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是3点
结果是	小
现在是第10场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是5点
结果是	大
现在是第11场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是5点
结果是	大
现在是第12场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是6点
结果是	大
现在是第13场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是1点
结果是	小
现在是第14场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是5点
结果是	大
现在是第15场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是6点
结果是	大
现在是第16场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是6点
结果是	大
现在是第17场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是1点
结果是	小
现在是第18场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是3点
结果是	小
现在是第19场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是3点
结果是	小
现在是第20场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是3点
结果是	小
现在是第21场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是1点
结果是	小
现在是第22场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是6点
结果是	大
现在是第23场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是4点
结果是	大
现在是第24场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是1点
结果是	小
现在是第25场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是5点
结果是	大
现在是第26场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是2点
结果是	小
现在是第27场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是3点
结果是	小
现在是第28场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是6点
结果是	大
现在是第29场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是4点
结果是	大
现在是第30场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是1点
结果是	小
现在是第31场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是2点
结果是	小
现在是第32场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是5点
结果是	大
现在是第33场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是4点
结果是	大
现在是第34场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是6点
结果是	大
现在是第35场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是1点
结果是	小
现在是第36场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是2点
结果是	小
现在是第37场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是1点
结果是	小
现在是第38场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是3点
结果是	小
现在是第39场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是2点
结果是	小
现在是第40场游戏
小明	压	小
小虎	压	大
热点	压	大
点数是1点
结果是	小
现在是第41场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是4点
结果是	大
现在是第42场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是1点
结果是	小
现在是第43场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是1点
结果是	小
现在是第44场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是3点
结果是	小
现在是第45场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是3点
结果是	小
现在是第46场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是2点
结果是	小
现在是第47场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是4点
结果是	大
现在是第48场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是6点
结果是	大
现在是第49场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是4点
结果是	大
现在是第50场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是3点
结果是	小
现在是第51场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是5点
结果是	大
现在是第52场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是1点
结果是	小
现在是第53场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是4点
结果是	大
现在是第54场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是5点
结果是	大
现在是第55场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是3点
结果是	小
现在是第56场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是3点
结果是	小
现在是第57场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是5点
结果是	大
现在是第58场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是2点
结果是	小
现在是第59场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是2点
结果是	小
现在是第60场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是2点
结果是	小
现在是第61场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是1点
结果是	小
现在是第62场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是4点
结果是	大
现在是第63场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是1点
结果是	小
现在是第64场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是5点
结果是	大
现在是第65场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是6点
结果是	大
现在是第66场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是5点
结果是	大
现在是第67场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是4点
结果是	大
现在是第68场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是3点
结果是	小
现在是第69场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是3点
结果是	小
现在是第70场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是3点
结果是	小
现在是第71场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是1点
结果是	小
现在是第72场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是1点
结果是	小
现在是第73场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是4点
结果是	大
现在是第74场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是5点
结果是	大
现在是第75场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是1点
结果是	小
现在是第76场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是5点
结果是	大
现在是第77场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是4点
结果是	大
现在是第78场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是3点
结果是	小
现在是第79场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是2点
结果是	小
现在是第80场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是3点
结果是	小
现在是第81场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是3点
结果是	小
现在是第82场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是4点
结果是	大
现在是第83场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是5点
结果是	大
现在是第84场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是2点
结果是	小
现在是第85场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是5点
结果是	大
现在是第86场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是2点
结果是	小
现在是第87场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是3点
结果是	小
现在是第88场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是3点
结果是	小
现在是第89场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是4点
结果是	大
现在是第90场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是4点
结果是	大
现在是第91场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是6点
结果是	大
现在是第92场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是5点
结果是	大
现在是第93场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是3点
结果是	小
现在是第94场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是6点
结果是	大
现在是第95场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是1点
结果是	小
现在是第96场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是4点
结果是	大
现在是第97场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是2点
结果是	小
现在是第98场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是1点
结果是	小
现在是第99场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是2点
结果是	小
现在是第100场游戏
小明	压	小
小虎	压	大
热点	压	小
点数是4点
结果是	大
总共100局游戏

我是小明
我赢了53局
我输了47局
我使用的是cn.com.startimes.strategy.FollowWin策略

我是小虎
我赢了47局
我输了53局
我使用的是cn.com.startimes.strategy.OppositeWin策略

我是热点
我赢了47局
我输了53局
我使用的是cn.com.startimes.strategy.HotWin策略

开头传送门

3.9 10个骰子,100000局

骰子个数
10
游戏局数
100000
总共100000局游戏

我是小明
我赢了50228局
我输了49772局
我使用的是cn.com.startimes.strategy.FollowWin策略

我是小虎
我赢了49772局
我输了50228局
我使用的是cn.com.startimes.strategy.OppositeWin策略

我是热点
我赢了50197局
我输了49803局
我使用的是cn.com.startimes.strategy.HotWin策略

3.10 1000个骰子,10 0000 局

总共100000局游戏

我是小明
我赢了50248局
我输了49752局
我使用的是cn.com.startimes.strategy.FollowWin策略

我是小虎
我赢了49752局
我输了50248局
我使用的是cn.com.startimes.strategy.OppositeWin策略

我是热点
我赢了50131局
我输了49869局
我使用的是cn.com.startimes.strategy.HotWin策略

4.总结

可以看到我们对压大小的策略使用了策略模式,但是现在实现的只有一个压大小,因为是play这个类实现委托的,所以,能否对play类使用策略模式,完成不同的玩法,压点数,奇偶等等。。。

另一个看到我们模拟这么多次试验,骰子出现大小的几率几乎是相等的,所以说,压大小几乎是最公平的游戏。
23种设计模式

    原文作者:算法小白
    原文地址: https://blog.csdn.net/a18792721831/article/details/83896933
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞