成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

掌握J(rèn)ava函數(shù)式接口,輕松實現(xiàn)依賴反轉(zhuǎn)

開發(fā) 前端
Java函數(shù)式接口是多年前引入的,它們對我們開發(fā)Java的方式產(chǎn)生了很大的影響。我們可以將它們用作lambda函數(shù),也可以用來反轉(zhuǎn)依賴關(guān)系,使我們的代碼更加簡潔。

你是否考慮過使用Java函數(shù)式接口來反轉(zhuǎn)Java項目內(nèi)的依賴關(guān)系?在本文中,我們將探討如何通過使用三個關(guān)鍵接口——Supplier、Consumer和Function來實現(xiàn)這一目標(biāo)。

1. Supplier

Supplier接口用于在不需要任何輸入?yún)?shù)的情況下提供一個對象,以下是Supplier接口的定義。

public interface Supplier{
   T get();
}

為了更好地理解使用這個接口的必要性,讓我們看一看下面的代碼。

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類負(fù)責(zé)在日志被啟用時寫入日志消息。Controller類通過調(diào)用generateLogMessage方法來向Logger類傳遞消息。到目前為止,一切看起來都很順利。

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

解決這個問題的辦法是向Logger類傳遞一個Supplier,它將在需要時返回消息,而Logger類只需在日志被啟用時調(diào)用該方法即可,代碼如下所示。

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());
   }
}

現(xiàn)在,generateLogMessage方法只會在Supplier的get方法被調(diào)用時執(zhí)行,這樣我們就能在日志未啟用時節(jié)省資源。此外,通過使用Supplier這種解決方案,我們可以靈活地實現(xiàn)復(fù)雜的日志記錄邏輯,并確保它只會在需要時被調(diào)用。

2. Function

通過Function接口,可以定義一個接收參數(shù)并產(chǎn)生結(jié)果的函數(shù)。以下是Function接口的定義(省略了一些默認(rèn)方法)。

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

為了開始探索Function接口,讓我們來看一個負(fù)責(zé)計算銷售訂單中商品價格的類。這個類需要接收輸入來計算最終價格,輸入包括產(chǎn)品、數(shù)量和適用的折扣(0到100之間)等。

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));

這個類首先計算總價,然后應(yīng)用折扣,再從總價中減去折扣金額。現(xiàn)在,讓我們考慮一個新的需求:對價格進(jìn)行貨幣轉(zhuǎn)換。

一種方法可能是直接將貨幣轉(zhuǎn)換邏輯添加到這個類中,這可能會帶來錯誤。更穩(wěn)健的解決方案是引入一個負(fù)責(zé)處理貨幣轉(zhuǎn)換的Function參數(shù)。

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));

增加這個新需求對代碼的影響很小,我們成功地反轉(zhuǎn)了依賴關(guān)系。PriceCalculator類不再需要處理貨幣轉(zhuǎn)換;相反,它只是用提供的函數(shù)調(diào)用凈價,并返回結(jié)果。這種設(shè)計使我們能夠在不修改PriceCalculator類的情況下,使用相同的類轉(zhuǎn)換為任何貨幣。

還有其他一些方法可以滿足這個需求,而不需要修改PriceCalculator類。你可以創(chuàng)建另一個類,充當(dāng)調(diào)用PriceCalculator的外觀,然后進(jìn)行貨幣轉(zhuǎn)換。通常,采用哪種解決方案是由具體項目決定的。

3. Consumer

Consumer接口支持定義一個接收參數(shù)、執(zhí)行特定任務(wù)但不返回任何值的函數(shù)。以下是Consumer接口的定義(省略了一些默認(rèn)方法)。

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

為了解Consumer接口的運行示例,我們來看看這個類,它在實體中設(shè)置了一些信息,并將其保存到數(shù)據(jù)庫中。

public class EntitySaver{
   public void create(Entity entity){
      entity.setCreationDate(new Date());
      database.insert(entity);
   }
}

// 使用示例
entitySaver.create(entity);

現(xiàn)在,假設(shè)我們需要在創(chuàng)建實體時通知其他類,但我們無法修改create方法的接口。在這種情況下,我們可以使用Consumer接口來實現(xiàn)發(fā)布-訂閱模式,下面是我們實現(xiàn)該模式的方法。

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);

在這個發(fā)布-訂閱模式的實現(xiàn)中,我們使用了Consumer接口。EntitySaver類現(xiàn)在維護(hù)了一個消費者列表,并包含了一個register方法來添加消費者到這個列表中。雖然create方法的接口保持不變,但我們引入了一行代碼來“消費”創(chuàng)建的實體,方法是調(diào)用已注冊的消費者。

4. 結(jié)語

Java函數(shù)式接口是多年前引入的,它們對我們開發(fā)Java的方式產(chǎn)生了很大的影響。我們可以將它們用作lambda函數(shù),也可以用來反轉(zhuǎn)依賴關(guān)系,使我們的代碼更加簡潔。

責(zé)任編輯:武曉燕 來源: Java學(xué)研大本營
相關(guān)推薦

2009-12-10 11:02:44

PHP函數(shù)eval()

2020-09-24 10:57:12

編程函數(shù)式前端

2024-02-27 08:22:56

2023-05-12 08:02:43

分布式事務(wù)應(yīng)用

2024-03-13 07:49:15

.NET依賴注入DI

2024-04-18 08:39:57

依賴注入控制反轉(zhuǎn)WPF

2010-01-13 17:47:59

VB.NET拖放

2009-12-17 14:36:57

Ruby on Rai

2024-02-28 08:37:28

Lambda表達(dá)式Java函數(shù)式接口

2024-04-15 07:00:00

Python開發(fā)Hatch

2024-05-10 07:19:46

IOC依賴倒置控制反轉(zhuǎn)

2023-10-20 08:01:08

2010-01-18 19:36:52

VB.NET調(diào)整控件

2022-04-30 08:50:11

控制反轉(zhuǎn)Spring依賴注入

2019-09-18 18:12:57

前端javascriptvue.js

2010-01-06 17:51:26

Linux關(guān)機命令

2022-11-06 21:50:59

Python編程函數(shù)定義

2024-07-18 08:00:00

2009-10-12 13:18:55

RHEL 4內(nèi)核

2014-10-30 16:12:55

編程技術(shù)算法
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 特黄特黄a级毛片免费专区 av网站免费在线观看 | 国产在线播 | 中文字幕视频在线免费 | 久久国产精品久久国产精品 | 日产久久 | 极品粉嫩国产48尤物在线播放 | 免费一区二区三区在线视频 | 99re免费| 久www| 91精品国产777在线观看 | 国产麻豆一区二区三区 | 99精品一区二区三区 | 91精品国产欧美一区二区成人 | 日韩欧美一区二区三区 | 日韩精品在线观看网站 | 久久精品色欧美aⅴ一区二区 | h片在线观看网站 | 久久91精品国产一区二区三区 | 国产日日操 | se婷婷| 日韩精品欧美精品 | 中文字幕一区在线 | 99视频免费在线 | 国产在线视频在线观看 | 91视频在线 | 亚洲精品一区二区冲田杏梨 | 天堂成人国产精品一区 | 日韩成人在线免费视频 | 一区二区免费看 | 伊人中文字幕 | 中文日韩在线 | 中文字幕一区二区三区四区五区 | 午夜一区二区三区在线观看 | 国产激情一区二区三区 | 日韩国产高清在线观看 | 免费一区二区三区 | 日本三级线观看 视频 | 99re视频在线| 欧美黄色片 | 天天夜碰日日摸日日澡 | 久久久久久久一区二区三区 |