设计模式学习笔记——策略(Strategy)模式

来源:互联网 发布:php导入excel到数据库 编辑:程序博客网 时间:2024/05/22 03:15

设计模式学习笔记——策略(Strategy)模式

@(设计模式)[设计模式, 策略模式, Stategy]

  • 设计模式学习笔记策略Strategy模式
    • 基本介绍
    • 策略案例
      • 类图
      • 实现代码
        • Hand类
        • Strategy接口
        • WinningStrategy类
        • ProbStrategy类
        • Player类
        • 测试类
        • 运行结果
    • 策略模式中的角色
      • Strategy策略
      • ConcreteStrategy具体的策略
      • Context上下文
      • 类图

基本介绍

策略模式主要用于整体切换解决方案,算法。一般使用委托来实现。

策略案例

类图

策略案例类图

实现代码

Hand类

package com.pc.strategy.example;/** * 猜拳手势类 * Created by Switch on 2017-02-20. */public class Hand {    private static final int HANDVALUE_ST = 0;  // 石头    private static final int HANDVALUE_JD = 1;  // 剪刀    private static final int HANDVALUE_BU = 2;  // 布    private int handValue;  // 手势值    // 手势值对应的手势名    private static final String[] name = {            "石头", "剪刀", "布"    };    // 手势实例    public static final Hand[] hand = {            new Hand(HANDVALUE_ST),            new Hand(HANDVALUE_JD),            new Hand(HANDVALUE_BU)    };    /**     * 构造方法,私有化,不能new出实例,注册表单例模式     *     * @param handValue 手势值     */    private Hand(int handValue) {        this.handValue = handValue;    }    /**     * 根据手势值,获取手势实例     *     * @param handValue 手势值     * @return 手势实例     */    public static Hand getHand(int handValue) {        return hand[handValue];    }    /**     * 赢了返回true     *     * @param hand 手势实例     * @return     */    public boolean isStrongerThan(Hand hand) {        return fight(hand) == 1;    }    /**     * 输了返回true     *     * @param hand 手势实例     * @return     */    public boolean isWeakerThan(Hand hand) {        return fight(hand) == -1;    }    /**     * 比较     *     * @param hand 手势实例     * @return     */    private int fight(Hand hand) {        if (this.handValue == hand.handValue) {            return 0;   // 平        } else if ((this.handValue + 1) % 3 == hand.handValue) {            return 1;   // 胜        } else {            return -1;  // 负        }    }    @Override    public String toString() {        // 手势值对应的手势名        return name[this.handValue];    }}

Strategy接口

package com.pc.strategy.example;/** * 猜拳策略接口 * Created by Switch on 2017-02-20. */public interface Strategy {    /**     * 下一个出拳手势     *     * @return 手势实例     */    Hand nextHand();    /**     * 根据上一次猜拳是否获胜,决定下一次的猜拳手势     *     * @param win 是否获胜     */    void study(boolean win);}

WinningStrategy类

package com.pc.strategy.example;import java.util.Random;/** * Winning策略类 * Created by Switch on 2017-02-20. */public class WinningStrategy implements Strategy {    private Random random; // 随机    private boolean won = false;    // 上一把是否赢了    private Hand prevHand;  // 上一把的手势对象    /**     * 构造方法,传入初始化随机seek     *     * @param seed 随机种子     */    public WinningStrategy(int seed) {        this.random = new Random(seed);    }    @Override    public Hand nextHand() {        if (!this.won) {            this.prevHand = Hand.getHand(this.random.nextInt(3));        }        return this.prevHand;    }    @Override    public void study(boolean win) {        this.won = win;    }}

ProbStrategy类

package com.pc.strategy.example;import java.util.Random;/** * Prob策略类 * Created by Switch on 2017-02-20. */public class ProbStrategy implements Strategy {    private Random random;  // 随机    private int prevHandValue;  // 上一把的手势值    private int currentHandValue; // 这一把的手势值    // 历史出拳概率数组    // history[上一把的手势值][这一把的手势值] 表示赢的次数    private int[][] history = {            {1, 1, 1},            {1, 1, 1},            {1, 1, 1}    };    /**     * 构造方法,传入初始化随机seek     *     * @param seed 随机种子     */    public ProbStrategy(int seed) {        this.random = new Random(seed);    }    @Override    public Hand nextHand() {        int randomValue = this.random.nextInt(this.getSum(this.currentHandValue));        int handValue = 0;        if (randomValue < this.history[this.currentHandValue][0]) {            // 当随机数在0到剪刀赢的次数时,赋值为0            handValue = 0;        } else if (randomValue < this.history[this.currentHandValue][0] + this.history[this.currentHandValue][1]) {            // 当随机数在剪刀赢的次数到石头赢得次数时,赋值为1            handValue = 1;        } else {            // 其他情况,赋值为2            handValue = 2;        }        // 当前值赋值为之前值        this.prevHandValue = this.currentHandValue;        // 计算出来的值赋值为当前值        this.currentHandValue = handValue;        return Hand.getHand(handValue);    }    /**     * 获取history[上一把的手势值][三种手势]赢的总次数     *     * @param hv 上一把的手势值     * @return history[上一把的手势值][三种手势]赢的总次数     */    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[上一把的手势值][这一把的手势]赢的次数加一            this.history[this.prevHandValue][this.currentHandValue]++;        } else {            // history[上一把的手势值][其他手势]赢的次数加一            this.history[this.prevHandValue][(this.currentHandValue + 1) % 3]++;            this.history[this.prevHandValue][(this.currentHandValue + 2) % 3]++;        }    }}

Player类

package com.pc.strategy.example;/** * 玩家类 * Created by Switch on 2017-02-20. */public class Player {    private String name; // 玩家名    private Strategy strategy; // 策略对象    private int wincount;   // 赢的次数    private int losecount;  // 输出次数    private int gamecount;  // 游戏总次数    /**     * 构造方法     *     * @param name     玩家名     * @param strategy 策略对象     */    public Player(String name, Strategy strategy) {        this.name = name;        this.strategy = strategy;    }    /**     * 策略决定下次要出的手势     *     * @return 手势对象     */    public Hand nextHand() {        return this.strategy.nextHand();    }    /**     * 赢     */    public void win() {        this.strategy.study(true);        this.wincount++;        this.gamecount++;    }    /**     * 输     */    public void lose() {        this.strategy.study(false);        this.losecount++;        this.gamecount++;    }    /**     * 平     */    public void even() {        this.gamecount++;    }    @Override    public String toString() {        return "[" + this.name + ":" + this.gamecount + " games, " + this.wincount + " win, " + this.losecount + " lose]";    }}

测试类

package com.pc.strategy.example.test;import com.pc.strategy.example.Hand;import com.pc.strategy.example.Player;import com.pc.strategy.example.ProbStrategy;import com.pc.strategy.example.WinningStrategy;import org.junit.Test;/** * Strategy Tester. * * @author Switch * @version 1.0 */public class StrategyTest {    /**     * 测试策略类     */    @Test    public void testStrategy() {        Player switchvov = new Player("switch", new WinningStrategy(54));        Player kity = new Player("kity", new ProbStrategy(32));        for (int i = 0; i < 10000; i++) {            Hand nextValue1 = switchvov.nextHand();            Hand nextValue2 = kity.nextHand();            if (nextValue1.isStrongerThan(nextValue2)) {                switchvov.win();                kity.lose();                System.out.println("Winner:" + switchvov);            } else if (nextValue1.isWeakerThan(nextValue2)) {                switchvov.lose();                kity.win();                System.out.println("Winner:" + kity);            } else {                System.out.println("Even...");                switchvov.even();                kity.even();            }        }        System.out.println("Total Result:");        System.out.println(switchvov);        System.out.println(kity);    }}

运行结果

Winner:[switch:1 games, 1 win, 0 lose]Winner:[switch:2 games, 2 win, 0 lose]Even...Winner:[kity:4 games, 1 win, 2 lose]Winner:[kity:5 games, 2 win, 2 lose]省略N行。。。Winner:[switch:9998 games, 3136 win, 3642 lose]Winner:[switch:9999 games, 3137 win, 3642 lose]Winner:[kity:10000 games, 3643 win, 3137 lose]Total Result:[switch:10000 games, 3137 win, 3643 lose][kity:10000 games, 3643 win, 3137 lose]

策略模式中的角色

Strategy(策略)

Strategy角色负责决定实现策略所必需的接口(API)。在案例中,由Strategy接口扮演此角色。

ConcreteStrategy(具体的策略)

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

Context(上下文)

负责使用Strategy角色。Context角色保存了ConcreteStrategy 角色的实例,并使用ConcreteStrategy角色去实现需求(总之,还是要调用Strategy角色的接口(API))。在案例中,由Player类扮演此角色。

类图

策略模式类图

GitHub:DesignPatternStudy

——————参考《图解设计模式》

0 0