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)什么是责任 责任是类间的一种合约或义务,也可以理解成一个业务功能,包括行为.数据.对象的创建等 知道责任——表示知道什么 行为责任 ...
随机推荐
- flask源码剖析系列(系列目录)
flask源码剖析系列(系列目录) 01 flask源码剖析之werkzurg 了解wsgi 02 flask源码剖析之flask快速使用 03 flask源码剖析之threading.local和高 ...
- 矩阵的基本性质 之 对称矩阵,Hermite矩阵,正交矩阵,酉矩阵
1.对称矩阵 2.Hermite矩阵 3.正交矩阵 4.酉矩阵
- 机器学习实战基础(二十七):sklearn中的降维算法PCA和SVD(八)PCA对手写数字数据集的降维
PCA对手写数字数据集的降维 1. 导入需要的模块和库 from sklearn.decomposition import PCA from sklearn.ensemble import Rando ...
- Django框架11 /form组件、modelForm组件
Django框架11 /form组件.modelForm组件 目录 Django框架11 /form组件.modelForm组件 1. form组件介绍 2. form常用字段与插件 3. form所 ...
- shaderlab - 9chapter-阴影
原理 相机和光源重合,相机能看到的表面,形成的深度图--叫做,阴影纹理(shadowMap). 传统的,用base和add更新深度信息,但是,此处需求是深度信息而已,掺杂了光的计算了,所以,unity ...
- Ethical Hacking - NETWORK PENETRATION TESTING(18)
Session Hijacking What if the user uses the "remember me" feature? If the user uses this f ...
- 【JVM之内存与垃圾回收篇】虚拟机栈
虚拟机栈 虚拟机栈概述 由于跨平台性的设计,Java 的指令都是根据栈来设计的.不同平台 CPU 架构不同,所以不能设计为基于寄存器的. 优点是跨平台,指令集小,编译器容易实现,缺点是性能下降,实现同 ...
- spring +ActiveMQ 实战 topic selecter指定接收
spring +ActiveMQ 实战 topic selecter指定接收 queue:点对点模式,一个消息只能由一个消费者接受 topic:一对多,发布/订阅模式,需要消费者都在线(可能会导致信息 ...
- Python 写入excel时的字体格式设置
转自:https://blog.csdn.net/kuangzhi9124/article/details/81940919 下面代码设置了单元格的字体.位置居中.框线,可以将格式调成自己需要的 im ...
- Zabbix添加监控主机
一.监控server本机 1.查看主机列表 2.启动server主机的zabbix-agent服务 [root@zabbix ~]# systemctl start zabbix-agent.serv ...