美文网首页
策略模式 -- 整体的替换算法

策略模式 -- 整体的替换算法

作者: 戴廿叁 | 来源:发表于2019-08-21 13:25 被阅读0次

1. 概述

所谓“策略”(strategy),即程序中的“算法”。策略模式(strategy pattern)可以整体的替换算法的实现部分,使得我们可以轻松的以不同的算法去解决同一个问题。

2. 模式类图

strategy-1.png

3. 模式角色

Strategy (策略)
Strategy 角色决定实现策略所必须的接口。

ConcreteStrategy (具体的策略)
ConcreteStrategy 角色负责实现 Strategy 角色的接口。

Context (上下文)
负责使用 Strategy 角色, Context中保存了 ConcreteStrategy 角色的实例,使用 ConcreteStrategy 角色的功能实现需求。

4. 代码示例

我们以猜拳游戏作为代码示例的实现需求。定义两种猜拳“策略”。第一种是,如果上次猜拳胜利,则此次使用相同的手势出拳。第二种略微复杂,根据上局猜拳胜利的概率,计算此次出拳的手势。

首先我们定义一个Hand类表示出拳。

Hand.java

public class Hand {
    public static final int HANDVALUE_S = 0;
    public static final int HANDVALUE_J = 1;
    public static final int HANDVALUE_B = 2;

    public static final Hand[] hand = {
            new Hand(HANDVALUE_S),
            new Hand(HANDVALUE_J),
            new Hand(HANDVALUE_B)
    };

    public 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 isStrongerThan(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;
        }
    }

    @Override
    public String toString() {
        return name[handValue];
    }

}

定义一个 Strategy 接口作为 Strategy 角色。它具有 nextHand() 和 study() API。 nextHand() 返回下次出拳手势。study() 用于决策下次出拳。

Strategy.java

public interface Strategy {
    Hand nextHand();

    void study(boolean win);
}

我们会有两种不同的策略,分别用 WinningStrategy 和 ProbStrategy 来实现

WinningStrategy.java

public class WinningStrategy implements Strategy {
    private boolean won;
    private Hand prevHand;
    private Random random;

    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;
    }
}

ProbStrategy.java

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

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

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

我们需要一个 Context 角色来使用策略,定义 Player 来完成猜拳的操作。

Player.java

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 getName(){
        return name;
    }

    @Override
    public String toString() {
        return "[" + name + ": " + gameCount + " games, " + winCount + " win, " + loseCount + " lose]";
    }
}

最后需要一个 Main 方法来调用

Main.java

public class Main {

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

        Player player1 = new Player("Aaron", new WinningStrategy(seed1));
        Player player2 = new Player("Tom", new ProbStrategy(seed2));

        for (int i = 0; i < 10000; i++) {
            Hand nextHand1 = player1.nextHand();
            Hand nextHand2 = player2.nextHand();

            if (nextHand1.isStrongerThan(nextHand2)) {
                System.out.println("Winner: " + player1.getName());
                player1.win();
                player2.lose();
            } else if (nextHand1.isWeakerThan(nextHand2)) {
                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());
    }
}

结果

Winner: Aaron
Winner: Tom
Even...
Winner: Tom
Even...
Winner: Tom
Even...
Winner: Aaron
Even...

... ...

Winner: Aaron
Winner: Tom
Winner: Aaron
Winner: Tom
Winner: Tom
Winner: Tom
Winner: Tom
Total result: 
[Aaron: 10000 games, 3160 win, 3564 lose]
[Tom: 10000 games, 3564 win, 3160 lose]

相关文章

  • 使用lambda表达式重构面向对象的设计模式(一)

    策略模式重构 策略模式中的策略在编程中其实就是算法,使用Sttrategy模式可以整体地替换算法的实现部分。能够整...

  • 设计模式-策略(Strategy)模式

    主要角色 策略 具体策略 职责 具体算法解决具体的问题,策略模式可以整体替换算法的实现,使用不同的算法解决同一个问...

  • 策略模式 -- 整体的替换算法

    1. 概述 所谓“策略”(strategy),即程序中的“算法”。策略模式(strategy pattern)可以...

  • 图解设计模式--Strategy(策略)模式

    整体地替换算法 Strategy 模式 整体替换算法的实现部分 示例程序 Hand.java Strategy.j...

  • Android开发笔记十七

    1.策略模式定义 策略模式,又叫算法簇模式,就是定义了不同的算法族,并且之间可以互相替换,此模式让算法的变化独立于...

  • 设计模式笔记(15)--策略模式

    策略模式 GOF对于策略模式的定义是:“策略模式定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法...

  • Strategy模式(设计模式)

    中心主旨:整体的替换算法 Strategy:策略,也就是算法的意思;这些都是为了解决问题; 这种模式主要目的是可以...

  • 策略模式

    什么是策略模式? 策略模式定义了一系列算法,并将算法封装起来,而且使他们可以相互替换。策略模式让算法独立于使用它的...

  • 《设计模式》之策略模式

    定义 策略模式:定义算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户 策略模式...

  • php设置模式之策略模式

    策略模式 策略模式定义一系列算法,将每个算法封装起来,并让他们可以相互替换.策略模式让算法独立于使用它的客户而变化...

网友评论

      本文标题:策略模式 -- 整体的替换算法

      本文链接:https://www.haomeiwen.com/subject/ecmbsctx.html