当前位置:首页 > 科技  > 软件

掌握Java函数式接口,轻松实现依赖反转

来源: 责编: 时间:2024-06-12 08:46:40 198观看
导读你是否考虑过使用Java函数式接口来反转Java项目内的依赖关系?在本文中,我们将探讨如何通过使用三个关键接口——Supplier、Consumer和Function来实现这一目标。1. SupplierSupplier接口用于在不需要任何输入参数的情况

你是否考虑过使用Java函数式接口来反转Java项目内的依赖关系?在本文中,我们将探讨如何通过使用三个关键接口——Supplier、Consumer和Function来实现这一目标。F5S28资讯网——每日最新资讯28at.com

1. Supplier

Supplier接口用于在不需要任何输入参数的情况下提供一个对象,以下是Supplier接口的定义。F5S28资讯网——每日最新资讯28at.com

public interface Supplier{   T get();}

为了更好地理解使用这个接口的必要性,让我们看一看下面的代码。F5S28资讯网——每日最新资讯28at.com

public class Logger{   public void log(String message){      if(isLogEnabled()){        write(message);      }   }}// 使用Logger类public class Controller{   @Inject Logger logger;   public void execute(){      logger.log(generateLogMessage());   }}

在上面的代码中,我们有一个Logger类负责在日志被启用时写入日志消息。Controller类通过调用generateLogMessage方法来向Logger类传递消息。到目前为止,一切看起来都很顺利。F5S28资讯网——每日最新资讯28at.com

然而,试想一下,如果generateLogMessage方法涉及大量处理或消耗大量资源,而日志记录又被禁用了,那么这些有价值的资源就白白浪费了,因为生成的日志消息不会被使用。F5S28资讯网——每日最新资讯28at.com

解决这个问题的办法是向Logger类传递一个Supplier,它将在需要时返回消息,而Logger类只需在日志被启用时调用该方法即可,代码如下所示。F5S28资讯网——每日最新资讯28at.com

public class Logger{   public void log(Supplier messageSupplier){      if(isLogEnabled()){        write(messageSupplier.get());      }   }}// 使用Logger类public class Controller{   @Inject Logger logger;   public void execute(){      logger.log(() -> generateLogMessage());   }}

现在,generateLogMessage方法只会在Supplier的get方法被调用时执行,这样我们就能在日志未启用时节省资源。此外,通过使用Supplier这种解决方案,我们可以灵活地实现复杂的日志记录逻辑,并确保它只会在需要时被调用。F5S28资讯网——每日最新资讯28at.com

2. Function

通过Function接口,可以定义一个接收参数并产生结果的函数。以下是Function接口的定义(省略了一些默认方法)。F5S28资讯网——每日最新资讯28at.com

public interface Function{   R apply(T t);}

为了开始探索Function接口,让我们来看一个负责计算销售订单中商品价格的类。这个类需要接收输入来计算最终价格,输入包括产品、数量和适用的折扣(0到100之间)等。F5S28资讯网——每日最新资讯28at.com

public class PriceCalculator{   public BigDecimal calculatePrice(Product product,                                     Integer quantity,                                    BigDecimal discount){     var grossPrice = product.getUnitPrice()                             .multiply(BigDecimal.valueOf(quantity));     var discountAmount = grossPrice.multiply(discount)                                    .divide(BigDecimal.valueOf(100));     return grossPrice.minus(discountAmount);   }}// 使用示例var result = priceCalculator(product, 10, BigDecimal.value(10));

这个类首先计算总价,然后应用折扣,再从总价中减去折扣金额。现在,让我们考虑一个新的需求:对价格进行货币转换。F5S28资讯网——每日最新资讯28at.com

一种方法可能是直接将货币转换逻辑添加到这个类中,这可能会带来错误。更稳健的解决方案是引入一个负责处理货币转换的Function参数。F5S28资讯网——每日最新资讯28at.com

public class PriceCalculator{   public BigDecimal calculatePrice(                        Product product,                         Integer quantity,                         BigDecimal discount,                         Function converterFunction){     var grossPrice = product.getUnitPrice()                             .multiply(BigDecimal.valueOf(quantity));     var discountAmount = grossPrice.multiply(discount)                                    .divide(BigDecimal.valueOf(100));     var netPrice = grossPrice.minus(discountAmount);     return converterFunction.apply(netPrice);   }}// 使用示例var result = priceCalculator(product,                              10,                              BigDecimal.value(10),                             netPrice -> netPrice.multiply(CURRENCY_RATE));

增加这个新需求对代码的影响很小,我们成功地反转了依赖关系。PriceCalculator类不再需要处理货币转换;相反,它只是用提供的函数调用净价,并返回结果。这种设计使我们能够在不修改PriceCalculator类的情况下,使用相同的类转换为任何货币。F5S28资讯网——每日最新资讯28at.com

还有其他一些方法可以满足这个需求,而不需要修改PriceCalculator类。你可以创建另一个类,充当调用PriceCalculator的外观,然后进行货币转换。通常,采用哪种解决方案是由具体项目决定的。F5S28资讯网——每日最新资讯28at.com

3. Consumer

Consumer接口支持定义一个接收参数、执行特定任务但不返回任何值的函数。以下是Consumer接口的定义(省略了一些默认方法)。F5S28资讯网——每日最新资讯28at.com

public interface Consumer{   void accept(T t);}

为了解Consumer接口的运行示例,我们来看看这个类,它在实体中设置了一些信息,并将其保存到数据库中。F5S28资讯网——每日最新资讯28at.com

public class EntitySaver{   public void create(Entity entity){      entity.setCreationDate(new Date());      database.insert(entity);   }}// 使用示例entitySaver.create(entity);

现在,假设我们需要在创建实体时通知其他类,但我们无法修改create方法的接口。在这种情况下,我们可以使用Consumer接口来实现发布-订阅模式,下面是我们实现该模式的方法。F5S28资讯网——每日最新资讯28at.com

public class EntitySaver{   private List> consumerList = new ArrayList<>();   public void register(Consumer consumer){      consumerList.add(consumer);   }   public void create(Entity entity){      entity.setCreationDate(new Date());      database.insert(entity);      consumerList.forEach(consumer -> consumer.accept(entity));   }}// 使用示例entitySaver.register(entity -> log.info(entity));entitySaver.register(entity -> mailerService.notifyUser(entity));entitySaver.create(entity);

在这个发布-订阅模式的实现中,我们使用了Consumer接口。EntitySaver类现在维护了一个消费者列表,并包含了一个register方法来添加消费者到这个列表中。虽然create方法的接口保持不变,但我们引入了一行代码来“消费”创建的实体,方法是调用已注册的消费者。F5S28资讯网——每日最新资讯28at.com

4. 结语

Java函数式接口是多年前引入的,它们对我们开发Java的方式产生了很大的影响。我们可以将它们用作lambda函数,也可以用来反转依赖关系,使我们的代码更加简洁。F5S28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-93210-0.html掌握Java函数式接口,轻松实现依赖反转

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: C# 实现动态访问 WebService,兼容 .NET Framework 和 .NET Core

下一篇: 七种 JavaScript 中位运算符的神奇用法

标签:
  • 热门焦点
  • 5月安卓手机好评榜:魅族20 Pro夺冠

    性能榜和性价比榜之后,我们来看最后的安卓手机好评榜,数据来源安兔兔评测,收集时间2023年5月1日至5月31日,仅限国内市场。第一名:魅族20 Pro好评率:97.50%不得不感慨魅族老品牌还
  • 把LangChain跑起来的三个方法

    使用LangChain开发LLM应用时,需要机器进行GLM部署,好多同学第一步就被劝退了,那么如何绕过这个步骤先学习LLM模型的应用,对Langchain进行快速上手?本片讲解3个把LangChain跑起来
  • 一年经验在二线城市面试后端的经验分享

    忠告这篇文章只适合2年内工作经验、甚至没有工作经验的朋友阅读。如果你是2年以上工作经验,请果断划走,对你没啥帮助~主人公这篇文章内容来自 「升职加薪」星球星友 的投稿,坐
  • 十个简单但很有用的Python装饰器

    装饰器(Decorators)是Python中一种强大而灵活的功能,用于修改或增强函数或类的行为。装饰器本质上是一个函数,它接受另一个函数或类作为参数,并返回一个新的函数或类。它们通常用
  • 使用AIGC工具提升安全工作效率

    在日常工作中,安全人员可能会涉及各种各样的安全任务,包括但不限于:开发某些安全工具的插件,满足自己特定的安全需求;自定义github搜索工具,快速查找所需的安全资料、漏洞poc、exp
  • 2023年,我眼中的字节跳动

    此时此刻(2023年7月),字节跳动从未上市,也从未公布过任何官方的上市计划;但是这并不妨碍它成为中国最受关注的互联网公司之一。从2016-17年的抖音强势崛起,到2018年的&ldquo;头腾
  • 腾讯VS网易,最卷游戏暑期档,谁能笑到最后?

    作者:无锈钵来源:财经无忌7月16日晚,上海1862时尚艺术中心。伴随着幻象的精准命中,硕大的荧幕之上,比分被定格在了14:12,被寄予厚望的EDG战队以绝对的优势战胜了BLG战队,拿下了总决
  • 冯提莫签约抖音公会 前“斗鱼一姐”消失在直播间

    来源:直播观察提起&ldquo;冯提莫&rdquo;这个名字,很多网友或许听过,但应该不记得她是哪位主播了。其实,作为曾经的&ldquo;斗鱼一姐&rdquo;,冯提莫在游戏直播的年代影响力不输于现
  • 超闭合精工铰链 彻底消灭缝隙 三星Galaxy Z Flip5与Galaxy Z Fold5发布

    2023年7月26日,三星电子正式发布了Galaxy Z Flip5与Galaxy Z Fold5。三星新一代折叠屏手机采用超闭合精工铰链,让折叠后的缝隙不再可见。同时,配合处
Top