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)什么是责任 责任是类间的一种合约或义务,也可以理解成一个业务功能,包括行为.数据.对象的创建等 知道责任——表示知道什么 行为责任 ...
随机推荐
- POJ 1050 To the Max 最详细的解题报告
题目来源:To the Max 题目大意:给定一个N*N的矩阵,求该矩阵中的某一个矩形,该矩形内各元素之和最大,即最大子矩阵问题. 解题方法:最大子序列之和的扩展 解题步骤: 1.定义一个N*N的矩阵 ...
- 《利用Python进行数据分析》自学知识图谱-导航
项目简介 Project Brief <利用Python进行数据分析-第二版>自学过程中整理的知识图谱. Python for Data Analysis: Data Wrangling ...
- 金三银四,资深HR给面试者的十大建议
一.提前复习好你的专业知识 专业知识是最为重要的一点,拥有了坚实的专业基础,你才能迈向成功的彼岸. 因此,面试之前,一定一定要复习好专业知识.对自己学过的知识,要做一个概括,放在脑海中.茶余饭后,复习 ...
- 少儿编程:python趣味编程第二课,如何在pygame中写文字
python趣味编程第二课:本文仅针对8-16岁的青少年,所以流程是按如何去教好中小学生走的,并不适合成人找工作学习,因为进度也是按照青少年走的 大家好,我是C大叔,上一篇文章已经跟大家介绍了一款开发 ...
- CUDA Programming Guide 学习笔记
CUDA学习笔记 GPU架构 GPU围绕流式多处理器(SM)的可扩展阵列搭建,每个GPU有多个SM,每个SM支持数百个线程并发执行.目前Nvidia推出了6种GPU架构(按时间顺序,详见下图):Fer ...
- C++语法小记---如何判断一个变量是不是指针
如何判断一个变量是不是指针? 思路:模板函数 + 可变参数 + sizeof(函数) #include <iostream> #include <string> using n ...
- 【Redis学习专题】- Redis主从+哨兵集群部署
集群版本: redis-4.0.14 集群节点: 节点角色 IP redis-master 10.100.8.21 redis-slave1 10.100.8.22 redis-slave2 10.1 ...
- 题解 洛谷 P6640 【[BJOI2020] 封印】
设\(lenth_i\)为\(s\)在\(i\)位置的前缀的后缀为\(t\)的一个子串的最长长度,即为从\(i\)位置开始往前和\(t\)的最长公共子串长度.其可以通过对\(t\)建后缀自动机,然后让 ...
- Python 编程语言的核心是什么?
01 Python 编程语言的核心是什么? 为什么要问这个问题? 我想要用Python实现WebAssembly,这并不是什么秘密.这不仅可以让Python进入浏览器,而且由于iOS和Andr ...
- .NET Core 微服务—API网关(Ocelot) 教程 [二]
上篇文章(.NET Core 微服务—API网关(Ocelot) 教程 [一])介绍了Ocelot 的相关介绍. 接下来就一起来看如何使用,让它运行起来. 环境准备 为了验证Ocelot 网关效果,我 ...