设计模式(十)-策略模式(Strategy Pattern)——整体的替换算法

原创 2018年01月31日 09:25:58

策略模式(Strategy Pattern)可以整体的替换算法的实现部分。

Hand.java

package com.test.dp.Strategy.Sample;

//算法需要计算的对象,这里代表“手势”
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 = {         // 表示猜拳中3种手势的实例
        new Hand(HANDVALUE_GUU),
        new Hand(HANDVALUE_CHO),
        new Hand(HANDVALUE_PAA),
    };
    private 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) {     // 如果this胜了h则返回true
        return fight(h) == 1;
    }
    public boolean isWeakerThan(Hand h) {       // 如果this输给了h则返回true
        return fight(h) == -1;
    }
    private int fight(Hand h) {                 // 计分:平0, 胜1, 负-1
        if (this == h) {
            return 0;
        } else if ((this.handvalue + 1) % 3 == h.handvalue) {
            return 1;
        } else {
            return -1;
        }
    }
    public String toString() {                  // 转换为手势值所对应的字符串
        return name[handvalue];
    }
}
Strategy.java

package com.test.dp.Strategy.Sample;

//策略抽象类
public interface Strategy {
    public abstract Hand nextHand();
    public abstract void study(boolean win);
}
WinningStrategy.java

package com.test.dp.Strategy.Sample;

import java.util.Random;

//策略算法实现:根据上一局的手势从概率上计算出下一局的手势从之前的猜拳结果计算下一局各种拳的概率
public class WinningStrategy implements Strategy {
    private Random random;
    private boolean won = false;
    private Hand prevHand;
    public WinningStrategy(int seed) {
        random = new Random(seed);
    }
    public Hand nextHand() {
        if (!won) {
            prevHand = Hand.getHand(random.nextInt(3));
        }
        return prevHand;
    }
    public void study(boolean win) {
        won = win;
    }
}
ProbStrategy.java

package com.test.dp.Strategy.Sample;

import java.util.Random;

//策略算法实现:如果这局猜拳获胜,那么下一局也出一样的手势
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);
    }
    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);
    }
    private int getSum(int hv) {
        int sum = 0;
        for (int i = 0; i < 3; i++) {
            sum += history[hv][i];
        }
        return sum;
    }
    public void study(boolean win) {
        if (win) {
            history[prevHandValue][currentHandValue]++;
        } else {
            history[prevHandValue][(currentHandValue + 1) % 3]++;
            history[prevHandValue][(currentHandValue + 2) % 3]++;
        }
    }
}
Player.java

package com.test.dp.Strategy.Sample;

//使用策略的对象,这里表示“猜拳玩家”
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 toString() {
        return "[" + name + ":" + gamecount + " games, " + wincount + " win, " + losecount + " lose" + "]";
    }
}
Main.java

package com.test.dp.Strategy.Sample;

public class Main {
    public static void main(String[] args) {
    	args = new String[]{"5", "6"};
        if (args.length != 2) {
            System.out.println("Usage: java Main randomseed1 randomseed2");
            System.out.println("Example: java Main 314 15");
            System.exit(0);
        }
        int seed1 = Integer.parseInt(args[0]);
        int seed2 = Integer.parseInt(args[1]);
        //两位猜拳的选手,采用不同的策略
        Player player1 = new Player("Taro", new WinningStrategy(seed1));
        Player player2 = new Player("Hana", 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);
                player1.win();
                player2.lose();
            } else if (nextHand2.isStrongerThan(nextHand1)) {
                System.out.println("Winner:" + player2);
                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:[Hana:7679 games, 2645 win, 2432 lose]
Winner:[Hana:7680 games, 2646 win, 2432 lose]
Even...
Even...
Winner:[Taro:7683 games, 2432 win, 2647 lose]
Even...
Winner:[Taro:7685 games, 2433 win, 2647 lose]
Even...
Winner:[Taro:7687 games, 2434 win, 2647 lose]
Even...
Winner:[Taro:7689 games, 2435 win, 2647 lose]
……此处省略若干行
Winner:[Taro:9996 games, 3178 win, 3449 lose]
Winner:[Taro:9997 games, 3179 win, 3449 lose]
Even...
Winner:[Hana:9999 games, 3449 win, 3180 lose]
Total result:
[Taro:10000 games, 3180 win, 3450 lose]
[Hana:10000 games, 3450 win, 3180 lose]
总结:

应用实例:1、诸葛亮的锦囊妙计,每一个锦囊就是一个策略。2、旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。3、JAVA AWT 中的 LayoutManager。

优点:1、算法可以自由切换。2、避免使用多重条件判断。3、扩展性良好。

缺点:1、策略类会增多。2、所有策略类都需要对外暴露。

使用场景:1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。2、一个系统需要动态地在几种算法中选择一种。3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。

注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。


Java设计模式——策略模式(Strategy Pattern)

Java设计模式——策略模式(Strategy Pattern) 场景一 描述:刘备要到江东娶老婆了,走之前诸葛亮给赵云(伴郎)三个锦囊妙计,说是按天机拆开解决棘手问题,嘿,还别说,真是解决了大问题,...
  • u012401711
  • u012401711
  • 2016年09月07日 21:16
  • 1115

Head First 设计模式——策略模式(Strategy Pattern)——Python实现

  本作品采用知识共享署名-非商业性使用-相同方式共享 3.0 Unported许可协议进行许可。允许非商业转载,但应注明作者及出处。 作者:liuyuan_jq2011-06-13 策略模式定义 定...
  • liuyuan_jq
  • liuyuan_jq
  • 2011年06月13日 17:41
  • 1481

浅谈JAVA设计模式之——策略模式(Strategy)

一、概述 定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。 二、适用性 1.许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为...
  • l1028386804
  • l1028386804
  • 2015年05月09日 14:02
  • 1892

我所理解的设计模式(C++实现)——策略模式(Strategy Pattern)

每个人都要“交个人所得税”,但是“在美国交个人所得税”和“在中国交个人所得税”就有不同的算税方法。 而策略模式就是对算法进行包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理。策略模式通...
  • LCL_data
  • LCL_data
  • 2013年08月24日 10:59
  • 12929

设计模式--深度解析策略模式(Strategy Pattern)

前些天网购一本Head First Design Patterns,学习了一下,觉得写的挺好,而且挺有趣的,推荐大家都去买一本,真心不错。在这里我先讲一下,这两天学的,两个常见的设计模式,分别Stra...
  • qq_29282475
  • qq_29282475
  • 2015年12月04日 14:17
  • 3560

C++设计模式<四>:策略模式(Strategy)

1.动机在软件构件过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂;而且有时候支持不使用的算法也是一个性能负担。2.模式定义定义一系列算法,把它们...
  • MonroeD
  • MonroeD
  • 2016年04月08日 01:16
  • 397

设计模式:策略模式(Python)

策略模式(Strategy Pattern): 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。 原则: 针对接口(...
  • ericzhong83
  • ericzhong83
  • 2012年05月17日 23:53
  • 4904

策略模式(Strategy Pattern)就这么简单

0x00 举个生活中的例子某个大人网站是会员制的,金牌会员购买精神食粮打7折,银牌会员打8折,铜牌会员打9折,铁牌会员不打折。也就是说不同的用户在购买精神食粮的时候结算的价格是不一样的,即使你们买相同...
  • fiendvip
  • fiendvip
  • 2016年04月12日 21:18
  • 4271

设计模式 - 策略模式(Strategy Pattern) 详解

策略模式(Strategy Pattern) 详解 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26577879 本文版...
  • u012515223
  • u012515223
  • 2014年05月22日 13:31
  • 2915

设计模式--spring源码中使用策略模式(Strategy Pattern)

策略模式(Strategy Pattern)中体现了两个非常基本的面向对象设计的基本原则:封装变化的概念;编程中使用接口,而不是对接口实现。策略模式的定义如下: 定义一组算法,将每个算法都封装起...
  • a137268431
  • a137268431
  • 2016年07月04日 17:32
  • 1227
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:设计模式(十)-策略模式(Strategy Pattern)——整体的替换算法
举报原因:
原因补充:

(最多只允许输入30个字)