10、Strategy 策略模式 整体地替换算法 行为型模式
1、模式说明
策略模式比较好理解,就是将程序中用到的算法整体的拿出来,并有多个不同版本的算法实现,在程序运行阶段,动态的决定使用哪个算法来解决问题。
2、举例
排序算法的问题,假如我们的程序中需要对数据进行排序,我们知道,不同的算法具有不同的时间复杂度和空间复杂度,因此需要在程序运行时,根据可用内存和数据特征,选用不同的算法(排序策略),这就是策略模式的使用场景之一。再举个例子,负载均衡算法:如果某个服务部署了多个冗余的实例,客户端在向服务端发送请求时,根据负载均衡算法策略,请求可能会被转发到不同的服务提供者实例来处理,如何决定某个请求转发给哪个服务实例呢,最简单的做法就是轮询,顺次将请求转发给每个服务实例进行处理。也可以采用随机方式,或者根据实际硬件环境和业务场景设置特定算法。
3、程序示例
在下面的演示策略模式的代码示例中,我们模拟猜拳游戏——剪刀石头布,猜拳的策略有两种:如果这次猜拳赢了,则下次还出同样的手势。另一种策略就是根据以前的猜拳结果,选择胜率最高的一种手势。
定义Hand类
package cn.design.behavior.strategy;/*** @author lin* @version 1.0* @date 2020-07-22 14:45* @Description TODO*/public class Hand {//表示石头public static final int HANDVALUE_ROCK = 0;//表示剪刀public static final int HANDVALUE_SCISSORS = 1;//表示布public static final int HANDVALUE_PEPER = 2;private static final Hand[] hand = {new Hand(HANDVALUE_ROCK),new Hand(HANDVALUE_SCISSORS),new Hand(HANDVALUE_PEPER)};private static final String[] name = {"石头", "剪刀", "布"};private final 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;}}@Overridepublic String toString() {return name[handValue];}}
定义Strategy接口
package cn.design.behavior.strategy;/*** @author lin* @version 1.0* @date 2020-07-22 14:50* @Description TODO*/public interface Strategy {public abstract Hand nextHand();public abstract void study(boolean win);}
定义ProbStrategy类
package cn.design.behavior.strategy;import java.util.Random;/*** @author lin* @version 1.0* @date 2020-07-22 14:51* @Description TODO*/public class ProbStrategy implements Strategy{private Random random;private int prevHandValue = 0;private int currentHandValue = 0;//history[上一局的手势][这一局的手势] 表达式的值越高表示过去的胜率越高//study方法会根据nextHand方法返回的手势胜负结果更新history字段中的值private int[][] history = {{1, 1, 1},{1, 1, 1},{1, 1, 1}};public ProbStrategy(int seed) {random = new Random(seed);}@Overridepublic Hand nextHand() {int bet = random.nextInt(getSum(currentHandValue));int handValue = 0;if (bet < history[currentHandValue][0]) {handValue = 0;}else if(bet < 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 : history[hv]) {sum += i;}return sum;}@Overridepublic void study(boolean win){if(win){history[prevHandValue][currentHandValue]++;}else{history[prevHandValue][(currentHandValue+1)%3]++;history[prevHandValue][(currentHandValue+2)%3]++;}}}
定义WinningStrategy类
package cn.design.behavior.strategy;import java.util.Random;/*** @author lin* @version 1.0* @date 2020-07-22 14:51* @Description TODO*/public class WinningStrategy implements Strategy {private Random random;private boolean won = false; //上一局的输赢结果private Hand prevHand; //上一局的手势public WinningStrategy(int seed) {random = new Random(seed);}@Overridepublic Hand nextHand() {if (!won) {prevHand = Hand.getHand(random.nextInt(3));}return prevHand;}@Overridepublic void study(boolean win) {won = win;}}
定义Player类
package cn.design.behavior.strategy;/*** @author lin* @version 1.0* @date 2020-07-22 14:52* @Description TODO*/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++;}@Overridepublic String toString(){return "[" + name + ":" + gamecount + " games, " + wincount +" win, " + losecount + " lose" + "]";}}
定义main测试类
package cn.design.behavior.strategy;import java.util.Random;/*** @author lin* @version 1.0* @date 2020-07-22 14:52* @Description TODO*/public class Main {public static void main(String[] args) {int seed1 = ((new Random()).nextInt(500)) * (1 + (new Random()).nextInt(500));int seed2 = seed1 * (new Random()).nextInt(500);Player player1 = new Player("Taro", new WinningStrategy(seed1));Player player2 = new Player("Hana", new ProbStrategy(seed2));for (int i = 0; i < 100000; 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);player2.win();player1.lose();} else {System.out.println("Even...");player1.even();player2.even();}}System.out.println("Total result:");System.out.println(player1.toString());System.out.println(player2.toString());}}
运行结果如下:
。。。Even...Winner: [Taro:99994 games, 37658 win, 27060 lose]Even...Even...Winner: [Taro:99997 games, 37659 win, 27060 lose]Winner: [Hana:99998 games, 27060 win, 37660 lose]Even...Total result:[Taro:100000 games, 37660 win, 27061 lose][Hana:100000 games, 27061 win, 37660 lose]
4、Strategy策略模式中的角色
Strategy策略:负责定义实现策略必须的接口方法
ConcreteStrategy具体的策略:实现Strategy角色的接口,如程序中的WinningStrategy和ProbStrategy
Context上下文:负责使用Strategy策略,如示例程序中的player。
5、相关的设计模式
Flyweight享元模式:通过使用享元模式,让多个地方共用ConcreteStrategy角色;
Abstract Factory抽象工厂:策略模式整体替换算法,抽象工厂整体替换具体的工厂,零件和产品;
State状态模式:状态模式和策略模式都可以替换被委托对象,而且类之间的关系也相似,只是两种模式目的不同。strategy策略模式替换被委托对象的类;状态模式中,每次状态发生变化时,被委托的对象必定会被替换。
公众号:发哥讲
这是一个稍偏基础和技术的公众号,甚至其中包括一些可能阅读量很低的包含代码的技术文,不知道你是不是喜欢,期待你的关注。

10、Strategy 策略模式 整体地替换算法 行为型模式的更多相关文章
- 设计模式学习之命令模式(Command,行为型模式)(12)
一.命令模式的定义 命令模式属于对象的行为型模式.命令模式是把一个操作或者行为抽象为一个对象中,通过对命令的抽象化来使得发出命令的责任和执行命令的责任分隔开.命令模式的实现可以提供命令的撤销和恢复功能 ...
- 设计模式学习之备忘录模式(Memento,行为型模式)(19)
假如我们已经记录一个人的个人信息,但是发现信息写错了,然后我先备份下再去修改,结果发现原来的信息是正确的,于是我就看备份的个人信息还原到初始的状态,下面我们用代码去实现 class Program { ...
- 设计模式学习之迭代器模式(Iterator,行为型模式)(17)
参考地址:http://www.cnblogs.com/zhili/p/IteratorPattern.html 一.介绍迭代器是针对集合对象而生的,对于集合对象而言,必然涉及到集合元素的添加删除操作 ...
- ANDROID 中设计模式的採用--创建型模式
所谓模式就是在某一情景下解决某个问题的固定解决方式. 全部的创建型模式都是用作对象的创建或实例化的解决方式. 1 简单工厂模式 创建对象的最简单方法是使用new来创建一个对象,假设仅仅创建一种固 ...
- 设计模式学习之访问者模式(Visitor,行为型模式)(21)
参考:https://www.cnblogs.com/edisonchou/p/7247990.html 在患者就医时,医生会根据病情开具处方单,很多医院都会存在以下这个流程:划价人员拿到处方单之后根 ...
- 设计模式学习之中介者模式(Mediator,行为型模式)(18)
转载地址:http://www.cnblogs.com/zhili/p/MediatorPattern.html 一.引言 在现实生活中,有很多中介者模式的身影,例如QQ游戏平台,聊天室.QQ群和短信 ...
- 责任链模式/chain of responsibility/行为型模式
职责链模式 chain of responsibility 意图 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处 ...
- 6、单例模式 Singleton模式 只有一个实例 创建型模式
1.了解Singleton模式 程序在运行时,通常都会生成很多实例.例如,表示字符串的java . lang . string类的实例与字符串是- -对- -的关系,所以当有1000个字符串的时候,会 ...
- OOAD-设计模式(二)之GRASP模式与GOF设计模式概述
一.GRASP模式(通用责任分配软件模式)概述 1.1.理解责任 1)什么是责任 责任是类间的一种合约或义务,也可以理解成一个业务功能,包括行为.数据.对象的创建等 知道责任——表示知道什么 行为责任 ...
随机推荐
- MVC + EFCore 项目实战 - 数仓管理系统4 – 需求分解
上次课程我们完成了项目基本的UI风格配置. 现在就开始进入我们的需求开发,我们先捋一下需求. 一.总体需求说明 项目背景第一篇文章已有介绍,我们回顾一下. 这是一个数据管理"工具类" ...
- day9 python之文件操作
1.文件操作 1.1 基本模式 # 格式 f = open("相对路径/绝对路径",mode = "模式",encoding = "编码级" ...
- 史上最全的 jmeter 获取 jdbc 数据使用的四种方法
jmeter使用jdbc协议获取数据库中数据,很多人都会用,因为大家在做测试的时候,有时候需要大量的用户进行登录,获取需要数据库中真实的数据用于测试,所以常常会用jdbc来获取数据库数据. 那从数据库 ...
- 【JUnit测试】总结
什么是Junit? Junit是xUnit的一个子集,在c++,paython,java语言中测试框架的名字都不相同 xUnit是一套基于测试驱动开发的测试框架 其中的断言机制:将程序预期的结果与程序 ...
- 性能1.84倍于Ceph!网易数帆Curve分布式存储开源
在上周刚结束的网易数字+大会上 网易数帆宣布: 开源一款名为Curve的高性能分布式存储系统, 性能可达Ceph的1.84倍! 网易副总裁.网易杭州研究院执行院长兼网易数帆总经理汪源: 基础软件的能力 ...
- Hadoop之HDFS常用文件操作命令
命令基本格式:hadoop fs -cmd < args > 1. ls 列出hdfs文件系统根目录下的目录和文件hadoop fs -ls /dirhadoop fs -ls -R /d ...
- 关于虎信如何绑定二次验证码_虚拟MFA_两步验证_谷歌身份验证器?
一般点账户名——设置——安全设置中开通虚拟MFA两步验证 具体步骤见链接 虎信如何绑定二次验证码_虚拟MFA_两步验证_谷歌身份验证器? 二次验证码小程序于谷歌身份验证器APP的优势 1.无需下载ap ...
- 获取DataGridview中某列的所有数据
/// <summary> /// /// </summary> /// <typeparam name="T"></typeparam& ...
- jmeter接口测试 -- Base64加密(函数助手添加自定义函数)
图片转码 base64 致谢参考博客: https://www.cnblogs.com/qiaoyeye/p/7218770.html https://www.cnblogs.com/lasdaybg ...
- Python break语句
Python break语句:当运行到 break 语句时,终止包含 break 的循环语句. 注:无论判断条件是否达到 False 或 序列是否遍历完都会停止执行循环语句和该 break 下的所有语 ...