设计模式(JAVA)——Strategy模式

1. Strategy模式

整体的替换算法或策略

1.1 Strategy模式的类图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P45y8vmC-1573652544809)(./resources/image/10/10-1_Strategy.png)]

登场的角色:

  • Strategy(策略)
    决定实现策略所必需的接口(API)

  • ConcreteStrategy(具体的策略)
    实现了Strategy角色的接口

  • Context(上下文)
    Context角色保存了ConcreteStrategy角色的实例,并使用了Strategy的接口。

1.2 示例程序

类一览表:

名字说明
Hand猜拳游戏中的“手势”类
Strategy猜拳游戏中的策略接口
WinningStrategy以“根据上一局猜拳获胜,那么下一局也出一样的手势”的策略实现类
ProbStratgey以“根据上一局的手势从概率上计算出下一局的手势从之前的猜拳结果计算下一局出各种拳的概率”的策略实现类
Player进行游戏的选手类
Main测试类

uml类图(只含继承关系)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LpZJ0nid-1573652544812)(./resources/image/10/10-2.png)]

uml类图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bVNuimF1-1573652544812)(./resources/image/10/10-3.png)]

Hand类

package xin.ajay.strategy;

public enum Hand {
    HANDVALUE_R("石头", 0), HANDVALUE_S("剪刀", 1), HANDVALUE_P("布", 2);

    private int value;
    private String name;

    private Hand(String name, int value) {
        this.name = name;
        this.value = value;
    }

    public static Hand getHand(int value) {
        switch (value) {
            case 0:
                return Hand.HANDVALUE_R;
            case 1:
                return Hand.HANDVALUE_S;
            case 2:
            default:
                return Hand.HANDVALUE_P;
        }
    }

    //平 0,胜 1,负 -1
    public int fight(Hand h) {
        if (this == h) {
            return 0;
        } else if ((this.value + 1) % 3 == h.value) {
            return 1;
        } else {
            return -1;
        }
    }

    @Override
    public String toString() {
        return "Hand{" + "name='" + name + '\'' + '}';
    }
}

Strategy接口

package xin.ajay.strategy;

public interface Strategy {

    //出手的策略
    Hand nextHand();

    //根据输赢进行学习
    void study(boolean win);
}

Player类

package xin.ajay.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++;
    }

    @Override
    public String toString() {
        return "Player{" + "name='" + name + '\'' + ", wincount=" + wincount + ", losecount=" + losecount + ", gamecount=" + gamecount + '}';
    }
}

WinningStrategy类

package xin.ajay.strategy;

import java.util.Random;

public class WinningStrategy implements Strategy {

    private Random random = new Random();
    private boolean won = false;
    private Hand prevHand;


    @Override
    public Hand nextHand() {
        if(!won){
            prevHand = Hand.getHand(random.nextInt(3));
        }
        return prevHand;
    }

    @Override
    public void study(boolean win) {
        won = win;
    }
}

ProbStratgey类

package xin.ajay.strategy;

import java.util.Random;

public class ProbStrategy implements Strategy {
    private Random random = new Random();
    private int prevHandValue = 0;
    private int currentHandValue = 0;

    //history[上局手势][这一局手势] 胜利的次数
    private int[][] history = new int[][]{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}};

    @Override
    public Hand nextHand() {
        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;
        prevHandValue = handvalue;

        return Hand.getHand(handvalue);

    }

    private int getSum(int hv){
        int sum = 0;
        for (int i = 0; i < 3; i++) {
            sum +=history[hv][i];
        }
        return sum;
    }


    //学习
    @Override
    public void study(boolean win) {
        if(win){
            history[prevHandValue][currentHandValue]++;
        }else {
            history[prevHandValue][(currentHandValue+1)%3]++;
            history[prevHandValue][(currentHandValue+2)%3]++;
        }
    }
}

Main类

package xin.ajay.strategy;

public class Main {
    public static void main(String[] args) {

        Player a = new Player("A", new WinningStrategy());
        Player b = new Player("B", new ProbStrategy());

        for (int i = 0; i < 10; i++) {
            Hand hand = a.nextHand();
            Hand hand1 = b.nextHand();
            switch (hand.fight(hand1)){
                case 0:
                    System.out.println("Winner:"+a);a.win();b.lose();break;
                case -1:
                    System.out.println("Winner:"+b);a.lose();b.win();break;
                case 1:
                    System.out.println("Even..");a.even();b.even();break;
            }
        }

        System.out.println("Total result:");
        System.out.println(a.toString());
        System.out.println(b.toString());


    }
}
鸣谢

GoF《设计模式》和结城浩的《图解设计模式》

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值