设计模式之策略模式

定义一系列的算法,把他们一个个封装起来,并且使他们可以相互替代。本模式使得算法可独立于使用它的客户而变化!

痛点

策略模式可以很好解决众多if问题
如以下:

package com.tao.YanMoDesignPattern.Strategy.notPattern;/*** @Author Mi_Tao* @Date 2023/7/22* @Description 价格管理,完成计算向客户所报价格的功能* @Version 1.0**/
public class Price {public double quoto(double goodsPrice,String customerType){if ("普通客户".equals(customerType)){System.out.println("对于新客户或者普通客户,没有折扣!");} else if ("老客户".equals(customerType)) {System.out.println("对于老客户,一律折扣5%!");return goodsPrice*(1-0.05);} else if ("大客户".equals(customerType)) {System.out.println("对于大客户,一律折扣10%!");return goodsPrice*(1-0.1);}return 0.0;}
}

先看一下标准的策略模式如何实现
上层接口,定义好行为

package com.tao.YanMoDesignPattern.Strategy.pattern;/*** @Author Mi_Tao* @Date 2023/7/22* @Description 策略,定义算法的接口* @Version 1.0**/
public interface Strategy {public void algorithmInterface();
}
package com.tao.YanMoDesignPattern.Strategy.pattern;/*** @Author Mi_Tao* @Date 2023/7/22* @Description* @Version 1.0**/
public class ConcreteStartegbA implements Strategy{@Overridepublic void algorithmInterface() {// 具体的算法实现}
}
package com.tao.YanMoDesignPattern.Strategy.pattern;/*** @Author Mi_Tao* @Date 2023/7/22* @Description* @Version 1.0**/
public class ConcreteStartegbB implements Strategy{@Overridepublic void algorithmInterface() {// 具体的算法实现}
}
package com.tao.YanMoDesignPattern.Strategy.pattern;/*** @Author Mi_Tao* @Date 2023/7/22* @Description* @Version 1.0**/
public class ConcreteStartegbC implements Strategy{@Overridepublic void algorithmInterface() {// 具体的算法实现}
}

核心实现

package com.tao.YanMoDesignPattern.Strategy.pattern;/*** @Author Mi_Tao* @Date 2023/7/22* @Description 上下文对象,通常会持有一个具体的策略对象* @Version 1.0**/
public class Context {// 持有一个具体的策略对象private Strategy strategy;/*** 上下文对客户端提供的操作接口,可以有参数和返回值*/public void contextInterface(){// 通常会转调具体的策略对象进行算法运算strategy.algorithmInterface();}
}

问题应用策略模式来解决

package com.tao.YanMoDesignPattern.Strategy.caseChange;/*** @Author Mi_Tao* @Date 2023/7/22* @Description 策略,定义计算报价算法的接口* @Version 1.0**/
public interface Strategy {/*** 计算应报的价格* @param goodsPrice* @return 计算出来的,应给客户的报价*/public double calcPrice(double goodsPrice);
}
package com.tao.YanMoDesignPattern.Strategy.caseChange;/*** @Author Mi_Tao* @Date 2023/7/22* @Description* @Version 1.0**/
public class OldCusomerStategy implements Strategy {@Overridepublic double calcPrice(double goodsPrice) {System.out.println("老客户,5%折扣");return goodsPrice*(1-0.05);}
}
package com.tao.YanMoDesignPattern.Strategy.caseChange;/*** @Author Mi_Tao* @Date 2023/7/22* @Description* @Version 1.0**/
public class NormalCusomerStategy implements Strategy {@Overridepublic double calcPrice(double goodsPrice) {System.out.println("普通客户,没有折扣");return goodsPrice;}
}
package com.tao.YanMoDesignPattern.Strategy.caseChange;/*** @Author Mi_Tao* @Date 2023/7/22* @Description* @Version 1.0**/
public class LargeCusomerStategy implements Strategy {@Overridepublic double calcPrice(double goodsPrice) {System.out.println("大客户,10%折扣");return goodsPrice*(1-0.1);}
}
package com.tao.YanMoDesignPattern.Strategy.caseChange;/*** @Author Mi_Tao* @Date 2023/7/22* @Description 价格管理,主要完成计算向客户所报价格的功能* @Version 1.0**/
public class Price {/*** 持有一个具体的策略对象*/private Strategy strategy = null;/*** 构造方法,传入一个具体的策略对象* @param strategy*/public Price(Strategy strategy) {this.strategy = strategy;}/*** 报价,计算客户的报价* @param goodsPrice 商品销售原价* @return 计算出来的,应该给客户的保教*/public double quote(double goodsPrice){return this.strategy.calcPrice(goodsPrice);}}

测试类

package com.tao.YanMoDesignPattern.Strategy.caseChange;/*** @Author Mi_Tao* @Date 2023/7/22* @Description* @Version 1.0**/
public class Client {public static void main(String[] args) {// 1、选择并创建需要使用的策略对象Strategy strategy = new LargeCusomerStategy();// 2、创建上下文Price ctx = new Price(strategy);//3、计算报价double quote = ctx.quote(1000);System.out.println("向客户报价:"+quote);}}

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
别提有多么舒服,只要改变实现的策略就可以进行逻辑的切换!

策略模式的中心不是如何实现算法,而是如何组织,调用这些算法, 从而让程序结构更灵活,具有更好的维护性和扩展性。

在这里插入图片描述
在这里插入图片描述

经典的策略模式调用顺序

在这里插入图片描述
在这里插入图片描述

除此之外还可以解决:容错问题(上传文件是中途失败,下次要如何恢复到失败的问题。实现模板方法模式)

经典的策略模式UML图

在这里插入图片描述
在这里插入图片描述

策略模式的本质: 分离算法,选择实现

何时使用策略模式

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/6399.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何让ChatGPT学习私有化知识,并且保留部分对话功能

问题情境 情景:比如我希望用 GPT 做一个产品的客服,现在有一些相关文档,如何让 GPT 学习到产品信息呢? 并且还具备正常对话功能 一个方案是直接把产品信息当做输入喂给GPT,但是ChatGPT/GPT-4/LLMs 一般都有输入长度的…

安装 PyCharm

网址:Download PyCharm: Python IDE for Professional Developers by JetBrains 安装文件: 第一步: 第二步: 第三步: 第四步: 正在安装: 安装完成:

pytest钩子函数(三):用例收集钩子

前言 pytest这个框架提供了非常多的钩子。通过这些钩子我们可以对pytest 用例收集、用例执行、报告输出等各个阶段进行干预,根据需求去开发对应的插件,以满足自己的使用场景。 01 什么是钩子函数? 钩子函数在pytest称之为Hook函数,它pytes…

Redis缓存击穿

Redis缓存击穿是指在使用Redis作为缓存时,某个热点数据过期或不存在,导致大量请求直接打到后端存储系统(例如数据库),使得后端系统压力骤增,性能下降的情况。这种情况通常发生在热点数据失效的瞬间。 缓存…

【高阶数据结构】B树

文章目录 一、B-树1. 常见的搜索结构2. B树概念3. B-树的查找4. B-树的插入分析 二、B树和B*树1. B树2. B*树 三、B-树的应用1. 索引2. MySQL索引简介2.1 MyISAM2.2 InnoDB 一、B-树 1. 常见的搜索结构 种类数据格式时间复杂度顺序查找无要求O(N)二分查找有序O(log2N)二叉搜索…

TCP/IP网络编程 第十九章:Windows平台下线程的使用

内核对象 要想掌握Windows平台下的线程,应首先理解“内核对象”(Kernel Objects)的概念。如果仅介绍Windows平台下的线程使用技巧,则可以省略相对陌生的内核对象相关内容。但这并不能使各位深入理解Windows平台下的线程。 内核对…

RocksDB架构

1、rocksdb是什么? RocksDB中文网 | 一个持久型的key-value存储 rocksdb是一种KV存储引擎,常用于数据库存储数据,无法直接使用,没有提供sql命令,通过调用rocksdb提供的api进行数据库的读写等操作。 rocksdb是以leveldb为基础开…

Linux一些问题,结合gpt,自己复习用

(一)请介绍linux以及它和windows的区别 🐧 Linux是一个开源的操作系统,它基于UNIX,并具有强大的自由度和灵活性。它被广泛用于服务器环境和嵌入式系统中。Linux有许多不同的发行版,例如Ubuntu、Debian、Fe…

聊聊spring-cloud的负载均衡

聊聊spring-cloud的负载均衡 1. 选择合适的负载均衡算法2. 合理设置超时时间3. 缓存服务实例列表4. 使用断路器5. 使用缓存Spring Cloud负载均衡组件对比RibbonLoadBalancerWebClient对比 总结 在微服务架构中,负载均衡是非常重要的一个环节,可以有效地提…

S32K144 GPIO外设分析

1. S32K144 GPIO外设特性 下面的内容来自于S32K用户手册的翻译,或者网上关于S32K系列的一些pdf文件介绍。有些内容可能会出现理解不到位或者翻译错误方面,如果大家有疑问最好可以查阅用户手册。 GPIO和PORT的数量 从用户手册,对于PCR&#x…

React Dva项目中路由跳转的方法

接下来 我们来看看路由跳转 先打开 我们Dva项目 然后我们需要在routes 下创建一个自己的路由,如果您尚未掌握在Dva项目中创建路由,可以参考我的文章 React 在Dva项目中修改路由配置,并创建一个自己的路由 然后 我的项目有两个路由 router.js…

ASFF Learning Spatial Fusion for Single-Shot Object Detection 论文学习

1. 解决了什么问题? 目标检测取得了显著成绩,但是检测不同尺度的目标仍然是一个挑战。金字塔或多层级特征是解决目标检测中尺度变化的常用手段。但对于单阶段目标检测器而言,各特征尺度之间不一致性制约了算法的表现。与图像金字塔相比&…

VMware Workstation 18 Tech Preview - 增强的 Windows 11 虚拟机安全性

VMware Workstation 18 Tech Preview - 增强的 Windows 11 虚拟机安全性 VMware Workstation Tech Preview 2023 请访问原文链接:https://sysin.org/blog/vmware-workstation-18/,查看最新版。原创作品,转载请保留出处。 作者主页&#xf…

OpenAI的Function calling 和 LangChain的Search Agent

OpenAI的Function calling openai最近发布的gpt-3.5-turbo-0613 和 gpt-4-0613版本模型增加了function calling的功能,该功能通过定义功能函数,gpt通过分析问题和函数功能描述来决定是否调用函数,并且生成函数对应的入参。函数调用的功能可以…

Pytorch个人学习记录总结 07

目录 神经网络-非线性激活 神经网络-线形层及其他层介绍 神经网络-非线性激活 官方文档地址:torch.nn — PyTorch 2.0 documentation 常用的:Sigmoid、ReLU、LeakyReLU等。 作用:为模型引入非线性特征,这样才能在训练过程中…

Java面试题总结记录(3)—— Spring篇

1、什么是Spring? Spring 是个java企业级应用的开源开发框架。Spring主要用来开发Java应用,但是有些扩展是针对 构建J2EE平台的web应用。 Spring 框架目标是简化Java企业级应用开发,并通过 POJO为基础的编程 模型促进良好的编程习惯 2、你们项…

Socks5代理在爬虫与HTTP应用中的重要性

IP代理的类型及原理常见的IP代理类型有HTTP代理、Socks代理等,本文重点关注Socks5代理。Socks5代理是一种网络协议,可以实现传输层的数据转发,使客户端在不直接连接服务器的情况下与其进行通信。其原理在于接收客户端的请求,然后将…

数组和链表、栈和队列的区别

1.数组和链表的区别 数组和链表是两种不同的数据结构,它们在存储和访问数据上有很大的区别。 1. 存储方式: 数组是一种连续内存空间的数据结构,其元素在内存中是按顺序存储的,通过索引可以直接访问元素。链表是由若干个节点组成…

[k8s] command和args

k8s中的command和args可以覆盖docker镜像中的entrypoint和cmd。其中,k8s-command可以覆盖docker-entrypoint,k8s-args可以覆盖docker-cmd。参考Difference between Docker ENTRYPOINT and Kubernetes container spec COMMAND? 了解一下entrypoint的意义…

Spring 更简单的读取和存储对象

目录 1.存储 Bean 对象 1.1 前置⼯作:配置扫描路径 1.2 添加注解存储 Bean 对象 1.2.1 Controller(控制器存储) 1.2.2 Service(服务存储) 1.2.3 Repository(仓库存储) 1.2.4 Component&a…