溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

java8怎么通過行為參數(shù)化傳遞代碼

發(fā)布時間:2022-10-18 16:12:28 來源:億速云 閱讀:89 作者:iii 欄目:編程語言

本篇內(nèi)容介紹了“java8怎么通過行為參數(shù)化傳遞代碼”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細閱讀,能夠?qū)W有所成!

應(yīng)對不斷變化的需求

編寫能夠應(yīng)對變化的需求的代碼并不容易。讓我們來看一個例子,我們會逐步改進這個例子,
以展示一些讓代碼更靈活的最佳做法。就農(nóng)場庫存程序而言,你必須實現(xiàn)一個從列表中篩選綠蘋
果的功能。聽起來很簡單吧?

第一個解決方案可能是下面這樣的:

/**
     *篩選綠蘋果
     * @param inventory 蘋果倉庫
     * @return
    public static List<Apple> filterGreenApples(List<Apple> inventory){
        List<Apple> result = new ArrayList<>();

        for(Apple apple:inventory){
            if ("green".equals(apple.getColor())){
                result.add(apple);
            }
        }
        return

現(xiàn)在農(nóng)民改主意了,他還想要篩選紅蘋果。
你該怎么做呢?簡單的解決辦法就是復(fù)制這個方法,把名字改成 filterRedApples ,然后更改
if 條件來匹配紅蘋果。然而,要是農(nóng)民想要篩選多種顏色:淺綠色、暗紅色、黃色等,這種方法
就應(yīng)付不了了。一個良好的原則是在編寫類似的代碼之后,嘗試將其抽象化。

/**
     * 把顏色參數(shù)化,應(yīng)對顏色變化的需求
     * @param inventory
     * @param color
     * @return
    public static List<Apple> filterApplesByColor(List<Apple> inventory,
                                                  String color) {
        List<Apple> result = new ArrayList<Apple>();
        for (Apple apple: inventory){
            if ( apple.getColor().equals(color) ) {
                result.add(apple);
            }
        }
        return

這時,農(nóng)民不斷提新需求,按重量刷選,按裝量和顏色篩選,于是你不斷修改代碼,粘貼復(fù)制,
一種把所有屬性結(jié)合起來的笨拙嘗試如下所示:

public static List<Apple> filterApples(List<Apple> inventory, String color,
int weight, boolean flag) {
        List<Apple> result = new ArrayList<Apple>();
        for (Apple apple: inventory){
                if ( (flag && apple.getColor().equals(color)) ||
                    (!flag && apple.getWeight() > weight) ){
                    result.add(apple);
                }
            }
        return

這個解決方案再差不過了。首先,客戶端代碼看上去糟透了。 true 和 false 是什么意思?此
外,這個解決方案還是不能很好地應(yīng)對變化的需求。如果這位農(nóng)民要求你對蘋果的不同屬性做篩
選,比如大小、形狀、產(chǎn)地等,又怎么辦?而且,如果農(nóng)民要求你組合屬性,做更復(fù)雜的查詢,
比如綠色的重蘋果,又該怎么辦?你會有好多個重復(fù)的 filter 方法,或一個巨大的非常復(fù)雜的
方法。

但如今這種情況下,你需要一種更好的方式,來把
蘋果的選擇標準告訴你的 filterApples 方法

行為參數(shù)化

你需要一種比添加很多參數(shù)更好的方法來應(yīng)對變化的需求。讓
我們后退一步來看看更高層次的抽象。

一種可能的解決方案是對你的選擇標準建模:你考慮的
是蘋果,需要根據(jù) Apple 的某些屬性(比如它是綠色的嗎?重量超過150克嗎?)來返回一個
boolean 值。我們把它稱為謂詞(即一個返回 boolean 值的函數(shù))。讓我們定義一個接口來對選
擇標準建模:

public interface ApplePredicate

    boolean

現(xiàn)在你就可以用 ApplePredicate 的多個實現(xiàn)代表不同的選擇標準了.

/**
 * 選出重蘋果的實現(xiàn)類
 *
 * @author itguang
 * @create
public class AppleHeavyWeightPredicate implements ApplePredicate{
    @Override
    public boolean test(Apple apple) {
        return apple.getWeight()>150;
    }
}
/**
 * 選出綠蘋果的實現(xiàn)類
 *
 * @author itguang
 * @create
public class AppleGreenColorPredicate implements ApplePredicate
    @Override
    public boolean test(Apple apple) {
        return "green".equals(apple.getColor());
    }
}

你可以把這些實現(xiàn)類看做filter方法的不同行為,剛做的這些和策略設(shè)計模式相關(guān),他讓你定義一簇算法(稱為 :策略),然后在運行時選擇一個算法。在這里,
算法族就是 ApplePredicate ,不同的策略就是 AppleHeavyWeightPredicate 和 AppleGreen-ColorPredicate 。

但是,該怎么利用 ApplePredicate 的不同實現(xiàn)呢?

你需要 filterApples 方法接受
ApplePredicate 對象,對 Apple 做條件測試。這就是行為參數(shù)化:讓方法接受多種行為(或戰(zhàn)
略)作為參數(shù),并在內(nèi)部使用,來完成不同的行為。

filter 方法看起來是這樣的:

“`java 
 /** 
 * 根據(jù)抽象條件進行篩選 
 * @param inventory 
 * @param applePredicate 
 * @return 
 */ 
 public static List filter(List inventory, ApplePredicate applePredicate){ 
 ArrayList list = new ArrayList<>(); 
 for (Apple apple:list){ 
 if(applePredicate.test(apple)){ 
 list.add(apple); 
 } 
 } 
 return list;}

“`
* 1. 傳遞代碼/行為:

這里值得停下來小小地慶祝一下。這段代碼比我們第一次嘗試的時候靈活多了,讀起來、用
起來也更容易!現(xiàn)在你可以創(chuàng)建不同的 ApplePredicate 對象,并將它們傳遞給 filterApples
方法.
你已經(jīng)做成了一件很酷的事: filterApples 方法的行為取決于你通過 ApplePredicate 對象傳遞的代碼。換句話說,你把 filterApples 方法的行為參數(shù)化了!

請注意,在上一個例子中,唯一重要的代碼是 test 方法的實現(xiàn),如圖2-2所示;正是它定義
了 filterApples 方法的新行為。但令人遺憾的是,由于該 filterApples 方法只能接受對象,
所以你必須把代碼包裹在 ApplePredicate 對象里。你的做法就類似于在內(nèi)聯(lián)“傳遞代碼”,因
為你是通過一個實現(xiàn)了 test 方法的對象來傳遞布爾表達式的

這就是說行為參數(shù)化是一個有用的概念的原因。你應(yīng)該把它放進你的工具箱里,用來編寫靈
活的API

對付啰嗦

到此,我們覺得已經(jīng)做的很好了,我們使用行為參數(shù)化解決了一些棘手的問題.
但是,目前來說,當要把新的行為傳遞給
filterApples 方法的時候,你不得不聲明好幾個實現(xiàn) ApplePredicate 接口的類,然后實例化
好幾個只會提到一次的 ApplePredicate 對象。

Java有一個機制稱為匿名類,它可以讓你同時
聲明和實例化一個類。它可以幫助你進一步改善代碼,讓它變得更簡潔。但這也不完全令人滿意。它往往很笨重,因為它占用了很多空間。

使用 Lambda 表達式

“`java 
 //將 List 類型抽象化 
 public static List filter(List list, Predicate p){ 
 List result = new ArrayList<>(); 
 for(T e: list){ 
 if(p.test(e)){ 
 result.add(e); 
 } 
 } 
 return result; 
 }
/**
     * 用Lambda表達式對倉庫的蘋果按重量升序排序
     */
    @Test
    public void test3(){
        List<Apple> inventory = initInventory();
        inventory.sort((Apple o1,Apple o2)->o1.getWeight().compareTo(o2.getWeight()));
        System.out.println(inventory);

    }

現(xiàn)在暫時不用擔(dān)心這個新語法,下一章我們會詳細講解如何編寫和使用Lambda表達式。

舉例2:用 Runnable 執(zhí)行代碼塊

線程就像是輕量級的進程:它們自己執(zhí)行一個代碼塊。但是,怎么才能告訴線程要執(zhí)行哪塊
代碼呢?多個線程可能會運行不同的代碼。我們需要一種方式來代表稍候執(zhí)行的一段代碼。在
Java里,你可以使用 Runnable 接口表示一個要執(zhí)行的代碼塊。請注意,代碼不會返回任何結(jié)果
(即 void ):

// java.lang.Runnable
public interface Runnable{
     public void run();
}

你可以像下面這樣,使用這個接口創(chuàng)建執(zhí)行不同行為的線程:

Thread t = new Thread(new Runnable() {
   public void run(){
       System.out.println("Hello world");
   }
});

用Lambda表達式的話,看起來是這樣:

Thread t = new Thread(() -> System.out.println("Hello world"));

“java8怎么通過行為參數(shù)化傳遞代碼”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI