Go和Java实现策略模式

Go和Java实现策略模式

模拟多种营销类型优惠券,折扣⾦额计算策略场景。

1、策略模式

在策略模式中一个类的行为或其算法可以在运行时更改,这种类型的设计模式属于行为型模式。

在策略模式定义了一系列算法或策略,并将每个算法封装在独立的类中,使得它们可以互相替换。通过使用策略模

式,可以在运行时根据需要选择不同的算法,而不需要修改客户端代码。

在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象,策略对象改变

context 对象的执行算法。

  • 意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。

  • 主要解决:在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。

  • 何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。

  • 如何解决:将这些算法封装成一个一个的类,任意地替换。

  • 关键代码:实现同一个接口。

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

    车,每一种旅行方式都是一个策略。 3、JAVA AWT 中的 LayoutManager。

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

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

  • 使用场景:1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动

    态地让一个对象在许多行为中选择一种行为。 2、一个系统需要动态地在几种算法中选择一种。 3、如果一个

    对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。

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

  • 策略模式包含以下几个核心角色:

    环境(Context):维护一个对策略对象的引用,负责将客户端请求委派给具体的策略对象执行。环境类可以

    通过依赖注入、简单工厂等方式来获取具体策略对象。

    抽象策略(Abstract Strategy):定义了策略对象的公共接口或抽象类,规定了具体策略类必须实现的方法。

    具体策略(Concrete Strategy):实现了抽象策略定义的接口或抽象类,包含了具体的算法实现。

  • 适用性:

    许多相关的类仅仅是行为有异,策略提供了一种用多个行为中的一个行为来配置一个类的方法。

    需要使用一个算法的不同变体。

    算法使用客户不应该知道的数据,可使用策略模式以避免暴露复杂的、与算法相关的数据结构。

    一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现,将相关的条件分支移入

    它们各自的 Strategy 类中以代替这些条件语句。

策略模式通过将算法与使用算法的代码解耦,提供了一种动态选择不同算法的方法。客户端代码不需要知道具体的

算法细节,而是通过调用环境类来使用所选择的策略。

2、Go实现策略模式

package strategy// 这里模拟多种营销类型优惠券,折扣⾦额计算
// 计算接口
type ICouponDiscount interface {// 参数1为正常支付、直减、满减、折扣、N元购// 参数2为金额// 返回为优惠后金额DiscountAmount(interface{}, float64) float64
}
package strategyimport ("reflect"
)// ==========满减==========
type MJCouponDiscount struct {
}// 这里参数为map,couponInfo["full"]=300,couponInfo["reduction"]=50
// 满多少钱减多少钱
func (mjCouponDiscount *MJCouponDiscount) DiscountAmount(couponInfo interface{}, price float64) float64 {var full float64var reduction float64if reflect.ValueOf(couponInfo).Kind() == reflect.Map {valueMap := reflect.ValueOf(couponInfo)full = valueMap.MapIndex(reflect.ValueOf("full")).Float()reduction = valueMap.MapIndex(reflect.ValueOf("reduction")).Float()}if price < full {return price} else {return price - reduction}
}
package strategy// ==========正常支付,不进行任何优惠==========
type NormalCouponDiscount struct {}// 正常支付
func (normalCouponDiscount *NormalCouponDiscount) DiscountAmount(couponInfo interface{}, price float64) float64 {return price
}
package strategy// ==========N元购买==========
type NYGCouponDiscount struct {
}// 打折
func (nygCouponDiscount *NYGCouponDiscount) DiscountAmount(couponInfo interface{}, price float64) float64 {return couponInfo.(float64)
}
package strategy// ==========直减====================
type ZJCouponDiscount struct {
}// 直接减多少钱
func (zjCouponDiscount *ZJCouponDiscount) DiscountAmount(couponInfo interface{}, price float64) float64 {return price - couponInfo.(float64)
}
package strategy// ==========折扣==========
type ZKCouponDiscount struct {
}// 打折
func (zkCouponDiscount *ZKCouponDiscount) DiscountAmount(couponInfo interface{}, price float64) float64 {return price * couponInfo.(float64)
}
package strategy// context
type CouponDiscountContext struct {ICouponDiscount
}func (couponDiscountContext *CouponDiscountContext) DoMethod(couponInfo interface{}, price float64) float64 {return couponDiscountContext.ICouponDiscount.DiscountAmount(couponInfo, price)
}
package mainimport ("fmt". "proj/strategy"
)func main() {var fullPrice float64 = 400var context CouponDiscountContextvar price float64// ==========满减==========var couponInfo map[string]float64couponInfo = make(map[string]float64)couponInfo["full"] = 300couponInfo["reduction"] = 50context = CouponDiscountContext{ICouponDiscount: &MJCouponDiscount{}}price = context.DiscountAmount(couponInfo, fullPrice)fmt.Println("满减 price: ", price)// ==========直减==========var reduction float64 = 100context = CouponDiscountContext{ICouponDiscount: &ZJCouponDiscount{}}price = context.DiscountAmount(reduction, fullPrice)fmt.Println("直减 price: ", price)// ==========打折==========var discounts float64 = 0.8context = CouponDiscountContext{ICouponDiscount: &ZKCouponDiscount{}}price = context.DiscountAmount(discounts, fullPrice)fmt.Println("打折 price: ", price)// ==========N元购==========var ny float64 = 9.9context = CouponDiscountContext{ICouponDiscount: &NYGCouponDiscount{}}price = context.DiscountAmount(ny, fullPrice)fmt.Println("N元购 price: ", price)// ==========正常支付==========var normal float64 = 0context = CouponDiscountContext{ICouponDiscount: &NormalCouponDiscount{}}price = context.DiscountAmount(normal, fullPrice)fmt.Println("正常支付 price: ", price)
}
# 程序输出
满减 price:  350
直减 price:  300
打折 price:  320
N元购 price:  9.9
正常支付 price:  400

3、Java实现策略模式

package com.strategy;// 这里模拟多种营销类型优惠券,折扣⾦额计算
// 计算接口
public interface ICouponDiscount<T> {// 参数1为正常支付、直减、满减、折扣、N元购// 参数2为金额// 返回为优惠后金额double discountAmount(T couponInfo, Double price);
}
package com.strategy;import java.util.Map;// ==========满减==========
public class MJCouponDiscount implements ICouponDiscount<Map<String, Double>> {// 这里参数为map,couponInfo["full"]=300,couponInfo["reduction"]=50// 满多少钱减多少钱@Overridepublic double discountAmount(Map<String, Double> couponInfo, Double price) {double full = couponInfo.get("full");double reduction = couponInfo.get("reduction");if (price > full) {return price - reduction;} else {return price;}}
}
package com.strategy;// ==========正常支付,不进行任何优惠==========
public class NormalCouponDiscount implements ICouponDiscount<Double> {// 正常支付@Overridepublic double discountAmount(Double couponInfo, Double price) {return price;}
}
package com.strategy;// ==========N元购买==========
public class NYGCouponDiscount implements ICouponDiscount<Double>{// 打折@Overridepublic double discountAmount(Double couponInfo, Double price) {return couponInfo;}
}
package com.strategy;// ==========直减====================
public class ZJCouponDiscount implements ICouponDiscount<Double> {// 直接减多少钱@Overridepublic double discountAmount(Double couponInfo, Double price) {return price - couponInfo;}
}
package com.strategy;// ==========折扣==========
public class ZKCouponDiscount implements ICouponDiscount<Double> {// 打折@Overridepublic double discountAmount(Double couponInfo, Double price) {return price * couponInfo;}
}
package com.strategy;// context
public class CouponDiscountContext<T> {private ICouponDiscount<T> iCouponDiscount;public CouponDiscountContext(ICouponDiscount<T> iCouponDiscount) {this.iCouponDiscount = iCouponDiscount;}public double discountAmount(T couponInfo, Double price) {return this.iCouponDiscount.discountAmount(couponInfo, price);}
}
package com.strategy;import java.util.HashMap;
import java.util.Map;public class Test {public static void main(String[] args) {Double fullPrice = new Double(400);Double price = new Double(0);// ==========满减==========Map<String, Double> couponInfo = new HashMap<>();couponInfo.put("full", new Double(300));couponInfo.put("reduction", new Double(50));CouponDiscountContext<Map<String, Double>> couponDiscountContext = new CouponDiscountContext<>(new MJCouponDiscount());price = couponDiscountContext.discountAmount(couponInfo, fullPrice);System.out.println("满减 price: " + price);// ==========直减==========Double reduction = new Double(100);CouponDiscountContext<Double> couponDiscountContext1 = new CouponDiscountContext<>(new ZJCouponDiscount());price = couponDiscountContext1.discountAmount(reduction, fullPrice);System.out.println("直减 price: " + price);// ==========打折==========Double discounts = new Double(0.8);CouponDiscountContext<Double> couponDiscountContext2 = new CouponDiscountContext<>(new ZKCouponDiscount());price = couponDiscountContext2.discountAmount(discounts, fullPrice);System.out.println("打折 price: " + price);// ==========N元购==========Double ny = new Double(9.9);CouponDiscountContext<Double> couponDiscountContext3 = new CouponDiscountContext<>(new NYGCouponDiscount());price = couponDiscountContext3.discountAmount(ny, fullPrice);System.out.println("N元购 price: " + price);// ==========正常支付==========Double normal = new Double(0);CouponDiscountContext<Double> couponDiscountContext4 = new CouponDiscountContext<>(new NormalCouponDiscount());price = couponDiscountContext4.discountAmount(normal, fullPrice);System.out.println("正常支付 price: " + price);}
}
# 程序输出
满减 price: 350.0
直减 price: 300.0
打折 price: 320.0
N元购 price: 9.9
正常支付 price: 400.0

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

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

相关文章

iOS/macOS - 逐行写入文件 (NSFileHandle)

文章目录 - (void)saveDataByLine{NSString *filePath = @"/Users/xx/Library/Containers/com.ds.TMXExport/Data/Library/Caches/a.txt";NSLog(@"filePath : %@", filePath);if (!

代码随想录算法训练营第五十天|123.买卖股票的最佳时机III、188.买卖股票的最佳时机IV

leetcode 123 买卖股票的最佳时机 III 题目链接 123. 买卖股票的最佳时机 III - 力扣&#xff08;LeetCode&#xff09; 做题过程 这里有两次交易机会。因此有5种状态。0没有操作&#xff0c;1第一次买入&#xff0c;2第一次卖出&#xff0c;3第二次买入&#xff0c;4第二次…

WebDAV之π-Disk派盘 + Solid Explorer

Solid Explorer 支持WebDAV方式连接π-Disk派盘。 Solid Explorer 是一款非常优秀的 Android 文件管理器&#xff0c;Material Design 设计风格&#xff0c;双栏布局&#xff0c;可拖拽操作、支持 ROOT 权限、多媒体浏览器、压缩包支持&#xff0c;Chromecast 流支持等众多功…

微信为什么使用 SQLite 保存聊天记录?

概要 SQLite 是一个被大家低估的数据库&#xff0c;但有些人认为它是一个不适合生产环境使用的玩具数据库。事实上&#xff0c;SQLite 是一个非常可靠的数据库&#xff0c;它可以处理 TB 级的数据&#xff0c;但它没有网络层。接下来&#xff0c;本文将与大家共同探讨 SQLite 在…

基于Tensorflow来重现GPT v1模型

OpenAI推出的ChatGPT模型让我们看到了通用人工智能的发展潜力&#xff0c;我也找了GPT的相关论文来进行研究。OpenAI在2017年的论文Improving Language Understanding by Generative Pre-Training提出了GPT的第一个版本&#xff0c;我也基于这个论文来用Tensorflow进行了复现。…

Keepalived 安装与配置

安装 Keepalived apt -y install keepalived 里边有一个杠y&#xff0c;就是我安装的时候里面有yes&#xff0c;就直接是yes 添加 Keepalived 配置 安装好之后, 下一步就开始去来写这个配置文件了&#xff0c;就在这里面去建一个 etc 当中&#xff0c;就是在这个 etc 当中建一个…

认识企业级定时任务Quartz

文章目录 前言一、实现一个Quartz的小案例1.创建一个maven项目2.添加Quartz依赖3.创建一个配置文件配置Quartz信息4.创建一个Job类继承Job接口5.编写主方法逻辑进行测试6.测试运行结果 二、Job和JobDetail总结 前言 目前仍有大部分企业仍在使用Quartz这种定时任务框架&#xf…

45. 跳跃游戏 II (贪心)

题目链接&#xff1a;力扣 解题思路&#xff1a;贪心&#xff0c;尽可能地找到下一跳能够跳到的最远距离&#xff0c;这样到达终点时&#xff0c;所需跳跃次数最少 以nums [2,3,1,1,4,2]为例&#xff1a; 以当前位置begin作为起跳点&#xff0c;能够跳跃的最远距离为m&#…

7.7知识点

1.React.createElement() jsx语法是React.createElement()的语法糖 虚拟dom 本质是一个js对象(类型为Object) 虚拟dom属性比较少(轻),真实dom属性方法比较多,因为在react内部使用,没有挂载到真实dom中,所以不用很多真实dom中的属性。(…

MySQL每日一练:多表查询——连接查询、子查询

目录 1、首先创建员工表emp和部门表dept&#xff1a; dept表&#xff1a; emp表&#xff1a; 2、插入数据&#xff1a; dept表&#xff1a; emp表&#xff1a; 3、 按条件查找 1、首先创建员工表emp和部门表dept&#xff1a; dept表&#xff1a; create table dept (…

存储优化和Protobuf

存储优化和Protobuf 本文链接&#xff1a;https://blog.csdn.net/feather_wch/article/details/131649688 文章目录 存储优化和ProtobufAndroid存储方式Protobuf介绍使用原理 7z压缩 Android存储方式 1、Android存储方式 SharePreferenceSQLite: 复杂的数据结构File -> p…

以太网(Ethernet)入门了解

以太网&#xff08;Ethernet&#xff09;是一种常见的局域网&#xff08;LAN&#xff09;通信协议&#xff0c;它是由Xerox公司于1970年代中期开发的。以太网是一种基于广播技术的开放式网络协议&#xff0c;它允许设备在共享通信介质上进行通信。以下是关于以太网的基本概念、…

MySQL 多表查询练习

1.创建student和score表 CREATE TABLE student ( id INT(10) NOT NULL UNIQUE PRIMARY KEY , name VARCHAR(20) NOT NULL , sex VARCHAR(4) , birth YEAR, department VARCHAR(20) , address VARCHAR(50) );创建score表。SQL代码如下&#xff1a; CREATE TABLE s…

OpenCV 入门教程:Laplacian算子和Canny边缘检测

OpenCV 入门教程&#xff1a; Laplacian 算子和 Canny 边缘检测 导语一、Laplacian 算子二、Canny 边缘检测三、示例应用3.1 图像边缘检测3.2 边缘增强 总结 导语 边缘检测在图像处理和计算机视觉领域中起着重要的作用。 Laplacian 算子和 Canny 边缘检测是两种常用的边缘检测…

CAT1模块 EC800M HTTP使用总结记录

分享记录一下 CAT1 模块EC800 HTTP 协议使用流程 ...... by 矜辰所致目录 前言一、基础说明1.1 CAT1 与 4G1.2 EC800M 模块1.3 HTTP 二、开始使用2.1 硬件设计部分2.2 模块上电流程2.3 PDP 上下文2.3.1 什么是 SGSN 和 GGSN &#xff1f; 三、 HTTP 流程3.1 客户端3.1.1 PDP 上…

Spring MVC JSON 数据交互

&#x1f514; JSON 语法 | 菜鸟教程 为实现浏览器与控制器类之间的 JSON 数据交互&#xff0c; Spring MVC 提供了 MappingJackson2HttpMessageConverter 实现类默认处理 JSON 格式请求响应。该实现类利用 Jackson 开源包读写 JSON 数据&#xff0c;将 Java 对象转换为 JSO…

k8s发生故障,可以从哪些方面排查

目录 第一方面&#xff1a;审视集群状态 第二方面&#xff1a;追踪事件日志 第三方面&#xff1a;聚焦Pod状态 第四方面&#xff1a;检查网络连通性 第五方面&#xff1a;审视存储配置 第六方面&#xff1a;研究容器日志 第一方面&#xff1a;审视集群状态 K8S的集群状态…

Ubuntu18.04 系统安装 Docker

1、首先更新软件源&#xff1a; sudo apt-get updatesudo apt-get upgrade 2、安装Docker&#xff1a; sudo apt install docker -y 3、查看安装的Docker apt list docker 4、查看docker 进程 ps -ef|grep docker 5、查看docker 版本有问题 6、开启Docker服务 systemctl…

10_SPI_Flash 连续写实验

10_SPI_Flash 连续写实验 1. 实验目标2. 连续写方法3. 操作时序4. 流程框图4.1 顶层模块4.2 连续写模块 5. 波形图6. RTL6.1 flash_seq_wr_ctrl6.2 spi_flash_seq_wr 7. Testbench 1. 实验目标 使用页写指令&#xff0c;将串口发送过来的连续不定量数据写入 Flash。本实验中&a…

Web安全——数据库mysql学习

数据库mysql基础 Web安全分享一、数据库的基本操作1、MYSQL登录与退出2、MYSQL数据库的一些解释3、MYSQL注释符有三种&#xff1a; 二、数据库的一些基本操作1、数据库的增删改查(sql语句) 三、table 表的操作1、查看表结构2、查看表的内容3、建立表4、约束条件5、修改表的操作…