日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

掌握Java函數式接口,輕松實現依賴反轉

來源: 責編: 時間:2024-06-12 08:46:40 139觀看
導讀你是否考慮過使用Java函數式接口來反轉Java項目內的依賴關系?在本文中,我們將探討如何通過使用三個關鍵接口——Supplier、Consumer和Function來實現這一目標。1. SupplierSupplier接口用于在不需要任何輸入參數的情況

你是否考慮過使用Java函數式接口來反轉Java項目內的依賴關系?在本文中,我們將探討如何通過使用三個關鍵接口——Supplier、Consumer和Function來實現這一目標。ZgS28資訊網——每日最新資訊28at.com

1. Supplier

Supplier接口用于在不需要任何輸入參數的情況下提供一個對象,以下是Supplier接口的定義。ZgS28資訊網——每日最新資訊28at.com

public interface Supplier{   T get();}

為了更好地理解使用這個接口的必要性,讓我們看一看下面的代碼。ZgS28資訊網——每日最新資訊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類傳遞消息。到目前為止,一切看起來都很順利。ZgS28資訊網——每日最新資訊28at.com

然而,試想一下,如果generateLogMessage方法涉及大量處理或消耗大量資源,而日志記錄又被禁用了,那么這些有價值的資源就白白浪費了,因為生成的日志消息不會被使用。ZgS28資訊網——每日最新資訊28at.com

解決這個問題的辦法是向Logger類傳遞一個Supplier,它將在需要時返回消息,而Logger類只需在日志被啟用時調用該方法即可,代碼如下所示。ZgS28資訊網——每日最新資訊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這種解決方案,我們可以靈活地實現復雜的日志記錄邏輯,并確保它只會在需要時被調用。ZgS28資訊網——每日最新資訊28at.com

2. Function

通過Function接口,可以定義一個接收參數并產生結果的函數。以下是Function接口的定義(省略了一些默認方法)。ZgS28資訊網——每日最新資訊28at.com

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

為了開始探索Function接口,讓我們來看一個負責計算銷售訂單中商品價格的類。這個類需要接收輸入來計算最終價格,輸入包括產品、數量和適用的折扣(0到100之間)等。ZgS28資訊網——每日最新資訊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));

這個類首先計算總價,然后應用折扣,再從總價中減去折扣金額。現在,讓我們考慮一個新的需求:對價格進行貨幣轉換。ZgS28資訊網——每日最新資訊28at.com

一種方法可能是直接將貨幣轉換邏輯添加到這個類中,這可能會帶來錯誤。更穩健的解決方案是引入一個負責處理貨幣轉換的Function參數。ZgS28資訊網——每日最新資訊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類的情況下,使用相同的類轉換為任何貨幣。ZgS28資訊網——每日最新資訊28at.com

還有其他一些方法可以滿足這個需求,而不需要修改PriceCalculator類。你可以創建另一個類,充當調用PriceCalculator的外觀,然后進行貨幣轉換。通常,采用哪種解決方案是由具體項目決定的。ZgS28資訊網——每日最新資訊28at.com

3. Consumer

Consumer接口支持定義一個接收參數、執行特定任務但不返回任何值的函數。以下是Consumer接口的定義(省略了一些默認方法)。ZgS28資訊網——每日最新資訊28at.com

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

為了解Consumer接口的運行示例,我們來看看這個類,它在實體中設置了一些信息,并將其保存到數據庫中。ZgS28資訊網——每日最新資訊28at.com

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

現在,假設我們需要在創建實體時通知其他類,但我們無法修改create方法的接口。在這種情況下,我們可以使用Consumer接口來實現發布-訂閱模式,下面是我們實現該模式的方法。ZgS28資訊網——每日最新資訊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方法的接口保持不變,但我們引入了一行代碼來“消費”創建的實體,方法是調用已注冊的消費者。ZgS28資訊網——每日最新資訊28at.com

4. 結語

Java函數式接口是多年前引入的,它們對我們開發Java的方式產生了很大的影響。我們可以將它們用作lambda函數,也可以用來反轉依賴關系,使我們的代碼更加簡潔。ZgS28資訊網——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-93210-0.html掌握Java函數式接口,輕松實現依賴反轉

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: C# 實現動態訪問 WebService,兼容 .NET Framework 和 .NET Core

下一篇: 七種 JavaScript 中位運算符的神奇用法

標簽:
  • 熱門焦點
Top 主站蜘蛛池模板: 青田县| 乌兰浩特市| 漳平市| 彭山县| 射阳县| 开平市| 宁夏| 德州市| 平遥县| 文水县| 桂平市| 贵德县| 辉县市| 仁布县| 织金县| 会理县| 南康市| 丰台区| 紫金县| 秦皇岛市| 东台市| 黄山市| 新密市| 临江市| 华宁县| 高邮市| 荔浦县| 曲水县| 普格县| 阿拉善右旗| 忻城县| 仁怀市| 龙山县| 高青县| 乌兰浩特市| 林西县| 中牟县| 贞丰县| 天柱县| 山丹县| 中江县|