【函数式接口使用✈️✈️】通过具体的例子实现函数结合策略模式的使用

目录

前言

一、核心函数式接口

1. Consumer

2.  Supplier

3.  Function,>

二、场景模拟

         1.面向对象设计

2. 策略接口实现(以 Function 接口作为策略) 

三、对比


前言

        在 Java 8 中引入了Stream API 新特性,这使得函数式编程风格进一步得到巩固,其中伴随着Lambda 表达式和 Stream API 的广泛使用,另一种函数式接口风格亦可以简化代码提升可读性和拓展性,具体如下

一、核心函数式接口

1. Consumer<T>

  • 定义了一个接受单一输入参数并且无返回值的操作。常用于数据处理流程中的消费型操作,如打印日志、更新数据库等。
  •         List<String> names = Arrays.asList("Alice", "Bob", "Charlie");names.forEach(e-> System.out.println("Welcome login : "+e));// 这里是使用的Consumer<String>,给一个参数执行相关操作// 或者定义一个自定义ConsumerConsumer<String> logAction = name -> System.out.println("Logging action for: " + name);names.forEach(logAction);

2.  Supplier<T>

  • 定义了一个不接受任何参数但是会产生一个结果的方法引用。常用于提供数据来源或计算某个值。
  •         Supplier<Integer> randomIntSupplier = () -> ThreadLocalRandom.current().nextInt(1, 100);System.out.println(randomIntSupplier.get()); // 输出一个1到100之间的随机整数

3.  Function<T, R>

  • 定义了一个接受一个输入参数并产生一个输出结果的方法引用。常用于数据转换、映射或计算。
  •         List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);List<Double> doubles = numbers.stream().map((Function<Integer, Double>)                                 Integer::doubleValue).collect(Collectors.toList());doubles.forEach(System.out::println);// 或者自定义FunctionFunction<String, String> upperCaseTransformer = String::toUpperCase;String transformed = upperCaseTransformer.apply("hello"); // 输出 "HELLO"System.out.println(transformed);

二、场景模拟

         1.面向对象设计

        比如常见的促销活动中,不同的促销策略计算出商品的最终价格是不一样的,采用传统的面向对象设计的话,需要为每一个促销活动创建独立的方法或者类了,并在购物车类中通过直接调用相应的方法计算,如下:

public class ShoppingCart {//购物车中的商品列表private List<Product> products;//普通不打折,统计所有商品的价格即可public double calculateTotalPriceWithNormalPrice() {double totalPrice = products.stream().map(Product::getPrice).reduce(0.0, Double::sum);return totalPrice;}//促销打九折,统计商品价格的九折public double calculateTotalPriceWithTenPercentDiscount() {double totalPrice = products.stream().map(product -> product.getPrice() * 0.9).reduce(0.0, Double::sum);return totalPrice;}//促销直减50 ,小于0 的按照0元计算public double calculateTotalPriceWithFiftyDollarsOff() {double totalPrice = products.stream().map(product -> Math.max(product.getPrice() - 50.0, 0.0)).reduce(0.0, Double::sum);return totalPrice;}// 调用示例public void processCheckout(CheckoutType type) {switch (type) {case NORMAL_PRICE:double normalPrice = calculateTotalPriceWithNormalPrice();// 处理正常价格结算逻辑break;case TEN_PERCENT_DISCOUNT:double tenPercentDiscount = calculateTotalPriceWithTenPercentDiscount();// 处理九折结算逻辑break;case FIFTY_DOLLARS_OFF:double fiftyDollarsOff = calculateTotalPriceWithFiftyDollarsOff();// 处理直减50美元结算逻辑break;}}// 其他方法...
}enum CheckoutType {NORMAL_PRICE,TEN_PERCENT_DISCOUNT,FIFTY_DOLLARS_OFF
}

        这种方式增加了代码的耦合度,并且如果需要新增或者修改促销策略,就需要修改ShoppingCart类

2. 策略接口实现(以 Function 接口作为策略) 

import java.util.function.Function;public interface PromotionStrategy extends Function<Double, Double> {// 不需要额外的方法,因为Function本身就是一种策略(接受一个参数,返回一个结果),它接受原始价格并返回打折后的价格
}

        创建几个具体的策略实现

public class NormalPriceStrategy implements PromotionStrategy {@Overridepublic Double apply(Double originalPrice) {return originalPrice; // 正常价格,不做打折处理}
}public class TenPercentDiscountStrategy implements PromotionStrategy {@Overridepublic Double apply(Double originalPrice) {return originalPrice * 0.9; // 打九折}
}public class FiftyDollarsOffStrategy implements PromotionStrategy {@Overridepublic Double apply(Double originalPrice) {return Math.max(originalPrice - 50.0, 0.0); // 直减50美元,价格不能低于0}
}

            之后,在购物车计算逻辑中,可以根据用户选择的促销策略动态计算商品的价格:

public class ShoppingCart {private List<Product> products;private PromotionStrategy promotionStrategy;public ShoppingCart(PromotionStrategy strategy) {this.promotionStrategy = strategy;// 初始化产品列表...}public double calculateTotalPrice() {double totalPrice = products.stream().map(Product::getPrice).map(promotionStrategy).reduce(0.0, Double::sum);return totalPrice;}// 其他方法...
}// 使用示例:
ShoppingCart cart = new ShoppingCart(new TenPercentDiscountStrategy());
// 添加商品到cart...
double finalPrice = cart.calculateTotalPrice(); // 根据策略计算总价

        这个例子就是使用 PromotionStrategy 扮演了策略角色,不同的折扣策略通过实现 Function<Double,Double> 接口来决定如何计算折扣价,在使用时,可以根据需要选择并注入不同的策略实现。

三、对比

策略模式面向对象设计
优点
  • 开放封闭原则:策略模式鼓励对扩展开放,对修改封闭。当需要增加新的促销策略时,只需要增加一个新的策略类,不需要修改现有的购物车类或者其他已有代码。
  • 代码复用:每个策略类(如NormalPriceStrategyTenPercentDiscountStrategyFiftyDollarsOffStrategy)可以独立于购物车类使用,增强了代码的复用性。
  • 低耦合:购物车类与具体的促销策略解耦,使得系统更灵活,更容易维护。
  • 对于简单的场景,直接在购物车类中添加多个计算方法直观易懂,初学者更容易接受。
缺点
  • 策略种类增多时,可能会导致策略接口的家族变得庞大,若策略逻辑差异不大,可能会造成代码冗余。
  • 耦合度高:购物车类与具体的促销逻辑紧密耦合,当促销策略发生变化时,必须修改购物车类的代码。
  • 扩展困难:若促销策略种类增加,会导致购物车类的代码臃肿,且不利于代码维护。
  • 代码复用性差:对于每一种新的促销活动,都需要在购物车类中添加新的方法,无法直接复用现有逻辑。

        其实不难看出,在面对频繁变化的业务逻辑(如促销策略)时,策略模式的优势明显,它有助于代码的可维护性、扩展性和复用性。而在简单、固定的场景下,直接在购物车类中硬编码计算逻辑可能显得更为直接简单。然而,考虑到长期的软件迭代和维护成本,推荐采用策略模式来优化代码结构。

文末

        文章到这里就结束了~

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

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

相关文章

【IoTDB 线上小课 02】开源增益的大厂研发岗面经

还有友友不知道我们的【IoTDB 视频小课】系列吗&#xff1f; 关于 IoTDB&#xff0c;关于物联网&#xff0c;关于时序数据库&#xff0c;关于开源...给我们 5 分钟&#xff0c;持续学习&#xff0c;干货满满~ 5分钟学会 大厂研发岗面试 之前的第一期小课&#xff0c;我们听了 I…

1.总结串口的发送和接收功能使用到的函数2.总结DMA的作用,和DMA+空闲中断的使用方式3.使用PWM+ADC光敏电阻完成光控灯的实验

1.总结串口的发送和接收功能使用到的函数 串口发送函数&#xff1a;HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout) UART_HandleTypeDef *huart&#xff1a;指定要使用的串口 const uint8_t *pData&…

爬虫入门——Request请求

目录 前言 一、Requests是什么&#xff1f; 二、使用步骤 1.引入库 2.请求 3.响应 三.总结 前言 上一篇爬虫我们已经提及到了urllib库的使用&#xff0c;为了方便大家的使用过程&#xff0c;这里为大家介绍新的库来实现请求获取响应的库。 一、Requests是什么&#xff1…

如何确保美国站群服务器的安全性?

选择服务器安全性很重要&#xff0c;那么如何确保美国站群服务器的安全性&#xff0c;rak部落小编为您整理发布如何确保美国站群服务器的安全性。 确保美国站群服务器的安全性&#xff0c;您可以采取以下措施&#xff1a; - **定期更新和升级**&#xff1a;保持服务器操作系统和…

基于Python大数据的微博舆情分析,微博评论情感分析可视化系统

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

PCB Editor简单使用

先在OrCAD软件 导出画好的图&#xff1a; 去PCBEditor软件&#xff1a; 画版图框框&#xff1a; 可以手动画也可以代码画&#xff0c;前提是使用line的操作。 命令画 x 0 0 x 1000 0 x 1000 1000 X 0 1000 X 0 0 就可以了 显示格点 修改格点&#xff1a; 导入…

transformer上手(9)—— 翻译任务

运用 Transformers 库来完成翻译任务。翻译是典型的序列到序列 (sequence-to-sequence, Seq2Seq) 任务&#xff0c;即对于每一个输入序列都会输出一个对应的序列。翻译在任务形式上与许多其他任务很接近&#xff0c;例如&#xff1a; 文本摘要 (Summarization)&#xff1a;将长…

短视频素材在哪里找?8个视频素材免费网站大全

在当下这个视频内容越发重要的时代&#xff0c;获取多样化且高质量的视频素材对于提升任何视频项目的吸引力至关重要。为了帮助你探索更广阔的创意领域&#xff0c;这里有一系列精选的无水印视频素材网站&#xff0c;它们各具特色&#xff0c;能够为你的创作带来新的视觉体验和…

C++ 并发编程指南(11)原子操作 | 11.5、内存模型

文章目录 一、C 内存模型1、为什么需要内存模型&#xff1f; 前言 C 11标准中最重要的特性之一&#xff0c;是大多数程序员都不会关注的东西。它并不是新的语法特性&#xff0c;也不是新的类库功能&#xff0c;而是新的多线程感知内存模型。本文介绍的内存模型是指多线程编程方…

TLS v1.3 导致JetBrains IDE jdk.internal.net.http.common CPU占用高

开发环境 GoLand版本&#xff1a;2022.3.4 问题原因 JDK 中的 TLS v1.3 实现引起 解决办法 使用 SOCKS 代理代替HTTP代理 禁用 Space 和 Code With Me 插件 禁用 TLS v1.3&#xff0c;参考&#xff1a;https://stackoverflow.com/questions/54485755/java-11-httpclient-…

【R语言】概率密度图

概率密度图是用来表示连续型数据的分布情况的一种图形化方法。它通过在数据的取值范围内绘制一条曲线来描述数据的分布情况&#xff0c;曲线下的面积代表了在该范围内观察到某一数值的概率。具体来说&#xff0c;对于给定的连续型数据&#xff0c;概率密度图会使用核密度估计&a…

基于STM32的交通灯(OLED屏显示倒计时)的Proteus仿真

文章目录 一、前言二、交通灯1.题目要求2.思路3.画图正常情况模拟故障情况 4.软件 三、总结 一、前言 最近下载了Proteus仿真软件&#xff0c;闲来无事也试试画一个简单的仿真图。 有需要软件的朋友可以去我的另外一篇博客下载和安装。 自用Proteus(8.15)仿真下载安装过程&a…

【LeetCode: 189. 轮转数组 + 双指针】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

阿里云服务器租用4核8G配置多少钱一年?

阿里云服务器租用4核8G配置多少钱一年&#xff1f;700元一年。阿里云4核8G服务器租用优惠价格700元1年&#xff0c;配置为ECS通用算力型u1实例&#xff08;ecs.u1-c1m2.xlarge&#xff09;4核8G配置、1M到3M带宽可选、ESSD Entry系统盘20G到40G可选&#xff0c;CPU采用Intel(R)…

抖音小店怎么找厂家代发?“对接”,“沟通”一篇详解

哈喽~我是电商月月 做抖音小店无货源的新手朋友遇到的第一个难题就是&#xff0c;不知道怎么找厂家&#xff0c;找到厂家后又不知道聊些什么内容 今天我就来给大家分享一下我找厂家时用的方法&#xff0c;全是经验&#xff0c;建议牢记&#xff01; 一&#xff0c;怎么找 找…

Java语言开发的AI智慧导诊系统源码springboot+redis 3D互联网智导诊系统源码

Java语言开发的AI智慧导诊系统源码springbootredis 3D互联网智导诊系统源码 智慧导诊解决盲目就诊问题&#xff0c;减轻分诊工作压力。降低挂错号比例&#xff0c;优化就诊流程&#xff0c;有效提高线上线下医疗机构接诊效率。可通过人体画像选择症状部位&#xff0c;了解对应…

AIGC算法1:Layer normalization

1. Layer Normalization μ E ( X ) ← 1 H ∑ i 1 n x i σ ← Var ⁡ ( x ) 1 H ∑ i 1 H ( x i − μ ) 2 ϵ y x − E ( x ) Var ⁡ ( X ) ϵ ⋅ γ β \begin{gathered}\muE(X) \leftarrow \frac{1}{H} \sum_{i1}^n x_i \\ \sigma \leftarrow \operatorname{Var}(…

cesium 解决带高度的polygon 材质不能透明的问题

问题描述&#xff1a;创建一个带高度的polygon&#xff0c;用一个带透明度的图片做材质&#xff0c;画出来的多边形没有透明效果&#xff0c;图片的透明通道没有用上。 一、创建不带高度polygon 不带高度的polygon&#xff0c;使用带透明度的图片是有效果的&#xff0c;但是不…

开源版中文和越南语贷款源码贷款平台下载 小额贷款系统 贷款源码运营版

后台 代理 前端均为vue源码&#xff0c;前端有中文和越南语 前端ui黄色大气&#xff0c;逻辑操作简单&#xff0c;注册可对接国际短信&#xff0c;可不对接 用户注册进去填写资料&#xff0c;后台审批&#xff0c;审批状态可自定义修改文字显示 源码免费下载地址抄笔记 (chaob…

常见面试算法题-数组二叉数

■ 题目描述 【数组二叉树】 二叉树也可以用数组来存储&#xff0c;给定一个数组&#xff0c;树的根节点的值存储在下标1&#xff0c;对于存储在下标N的节点&#xff0c;它的左子节点和右子节点分别存储在下标2*N和2*N1&#xff0c;并且我们用值-1代表一个节点为空。 给定一…