Java设计模式-策略模式(十)

 

目录

 

一、什么是策略模式

二、示例程序

三、UML

四、拓展思路与注意事项

1、为什么需要特意编写Strategy角色

2、程序运行中也可以切换策略

3、策略模式的优点

4、策略模式的缺点

5、策略模式的使用场景


一、什么是策略模式

策略模式(Strategy Method)是一种比较简单的模式,也叫做政策模式,其定义如下:定义一组算法,将每个算法都封装起来,并且使他们之间相互切换。

二、示例程序

 

 

1、Hand类

package com.as.module.stratege;

/**
 * 手势类
 * @author Andy
 * @date 2021/5/9 22:48
 */
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),
    };
    public static final String[] name = {
            "石头","剪刀","布"
    };

    private int handvalue;

    public Hand(int handvalue) {
        this.handvalue = handvalue;
    }

    public static Hand getHand(int handvalue){
        return hand[handvalue];
    }

    public boolean isStrongThan(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];
    }


}

2、Strategy接口

package com.as.module.stratege;

/**
 * 策略接口
 * @author Andy
 * @date 2021/5/9 22:59
 */
public interface Strategy {
    public abstract Hand nextHand();
    public abstract void study(boolean win);

}

3、WinningStrategy接口

package com.as.module.stratege;

import java.util.Random;

/**
 * TODO
 *
 * @author Andy
 * @date 2021/5/9 23:00
 */
public class WinningStrategy implements Strategy {
    private Random random;
    private boolean won = false;
    private Hand prevHand;

    public WinningStrategy(int seed){
        random = new Random(seed);
    }

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

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

4、ProbStrategy接口

package com.as.module.stratege;

import java.util.Random;

/**
 * TODO
 * @author Andy
 * @date 2021/5/10 21:28
 */
public class ProbStrategy implements Strategy{
    private Random random;
    private int preHandValue;
    private int currentHandValue;



    private int[][] history = {
            {1,1,1,},
            {1,1,1,},
            {1,1,1,},
    };

    public ProbStrategy(int seed) {
        this.random = new Random(seed);
    }

    @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;
        }
        preHandValue = currentHandValue;
        currentHandValue = handValue;
        return Hand.getHand(handValue);
    }

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

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


}

5、Player类

package com.as.module.stratege;

/**
 * 玩家
 * @author Andy
 * @date 2021/5/10 21:40
 */

public class Player {
    private String name;
    private Strategy strategy;
    private int wincount;
    private int losecount;
    private int gamecount;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Strategy getStrategy() {
        return strategy;
    }

    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }

    public int getWincount() {
        return wincount;
    }

    public void setWincount(int wincount) {
        this.wincount = wincount;
    }

    public int getLosecount() {
        return losecount;
    }

    public void setLosecount(int losecount) {
        this.losecount = losecount;
    }

    public int getGamecount() {
        return gamecount;
    }

    public void setGamecount(int gamecount) {
        this.gamecount = 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 + '\'' +
                ", strategy=" + strategy +
                ", wincount=" + wincount +
                ", losecount=" + losecount +
                ", gamecount=" + gamecount +
                '}';
    }
}

6、TestStrategy类

package com.as.module.stratege;

/**
 * 策略模式测试类
 * @author Andy
 * @date 2021/5/10 21:46
 */
public class TestStrategy {

    public static void main(String[] args) {
        int seed1 = 5;
        int seed2 = 6;

        Player player1 = new Player("Andy",new WinningStrategy(seed1));
        Player player2 = new Player("Lucy",new ProbStrategy(seed2));

        for(int i=0;i<10000;i++){
            Hand nextHandle1 = player1.nextHand();
            Hand nextHandle2 = player2.nextHand();
            if(nextHandle1.isStrongThan(nextHandle2)){
                System.out.println("winner:"+player1.getName());
                player1.win();
                player2.lose();
            }else if(nextHandle2.isStrongThan(nextHandle1)){
                System.out.println("winner:"+player2.getName());
                player1.lose();
                player2.win();
            }else{
                System.out.println("Even...");
                player1.even();
                player2.even();
            }

        }
        System.out.println("Total result:");
        System.out.println(player1.toString());
        System.out.println(player2.toString());

    }


}

 

三、UML

 

在Strategy模式中有以下登场角色。

1、Strategy(策略)

Strategy角色负责决定实现策略所必须的接口。在示例程序中,由Strategy接口扮演此角色。

2、ConcreteStrategy(具体的策略)

ConcreteStrategy角色负责实现Strategy角色的接口,即负责实现具体的策略(战略、方向、方法和算法)。在示例程序中,由WinningStrategy和ProbStrategy类扮演此角色。

3、Context(ontext(上下文)

负责使用Strategy角色。Context角色保存了ConcreteStrategy角色的实例,并使用ConcreteStrategy角色去实现需求。在示例程序中,由Player类扮演此角色

 

四、拓展思路与注意事项

1、为什么需要特意编写Strategy角色

    通常在编程时算法会被写在具体方法中。Strategy模式却特意将算法与其他部分分离开来,只是定义了与算法相关的接口,然后在程序中以委托的方式来使用算法。

    这样看起来程序好像变复杂了,其实不然。例如,当我们想要通过改善算法来提高算法的处理速度时,如果使用了Strategy模式,就不必修改Strategy角色的接口了,仅仅修改ConcreteStrategy角色即可。而且,使用委托这种弱关联关系可以很方便地整体替换算法

2、程序运行中也可以切换策略

    如果是Strategy模式,在程序运行中也可以切换ConcreteStrategy角色。例如,在内存容量少的运行环境中可以使用SlowButLessMemory(速度慢但是省内存的策略),而在内存容量比较多的环境中则可以使用FastButMoreMemoryStrategy(速度快但耗内存的策略)

3、策略模式的优点

(1) 算法可以自由切换

(2) 避免使用多重条件判断

(3) 扩展性良好

4、策略模式的缺点

(1)策略类数量众多

(2)所有的策略类都需要对外暴露

上层模块必须知道有哪些策略,然后才能决定使用哪个策略,这与迪米特法则是想违背的,但是,可以通过其他模式来修补这个缺陷,如工厂方法模式,代理模式,享元模式

5、策略模式的使用场景

(1)算法需要自由切换的场景

(2)需要屏蔽算法规则的场景

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值