您好,登錄后才能下訂單哦!
本篇內容介紹了“java8怎么通過行為參數化傳遞代碼”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
編寫能夠應對變化的需求的代碼并不容易。讓我們來看一個例子,我們會逐步改進這個例子,
以展示一些讓代碼更靈活的最佳做法。就農場庫存程序而言,你必須實現一個從列表中篩選綠蘋
果的功能。聽起來很簡單吧?
第一個解決方案可能是下面這樣的:
/** *篩選綠蘋果 * @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
現在農民改主意了,他還想要篩選紅蘋果。
你該怎么做呢?簡單的解決辦法就是復制這個方法,把名字改成 filterRedApples ,然后更改
if 條件來匹配紅蘋果。然而,要是農民想要篩選多種顏色:淺綠色、暗紅色、黃色等,這種方法
就應付不了了。一個良好的原則是在編寫類似的代碼之后,嘗試將其抽象化。
/** * 把顏色參數化,應對顏色變化的需求 * @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
這時,農民不斷提新需求,按重量刷選,按裝量和顏色篩選,于是你不斷修改代碼,粘貼復制,
一種把所有屬性結合起來的笨拙嘗試如下所示:
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 是什么意思?此
外,這個解決方案還是不能很好地應對變化的需求。如果這位農民要求你對蘋果的不同屬性做篩
選,比如大小、形狀、產地等,又怎么辦?而且,如果農民要求你組合屬性,做更復雜的查詢,
比如綠色的重蘋果,又該怎么辦?你會有好多個重復的 filter 方法,或一個巨大的非常復雜的
方法。
但如今這種情況下,你需要一種更好的方式,來把
蘋果的選擇標準告訴你的 filterApples 方法
你需要一種比添加很多參數更好的方法來應對變化的需求。讓
我們后退一步來看看更高層次的抽象。
一種可能的解決方案是對你的選擇標準建模:你考慮的
是蘋果,需要根據 Apple 的某些屬性(比如它是綠色的嗎?重量超過150克嗎?)來返回一個
boolean 值。我們把它稱為謂詞(即一個返回 boolean 值的函數)。讓我們定義一個接口來對選
擇標準建模:
public interface ApplePredicate boolean
現在你就可以用 ApplePredicate 的多個實現代表不同的選擇標準了.
/** * 選出重蘋果的實現類 * * @author itguang * @create public class AppleHeavyWeightPredicate implements ApplePredicate{ @Override public boolean test(Apple apple) { return apple.getWeight()>150; } }
/** * 選出綠蘋果的實現類 * * @author itguang * @create public class AppleGreenColorPredicate implements ApplePredicate @Override public boolean test(Apple apple) { return "green".equals(apple.getColor()); } }
你可以把這些實現類看做filter方法的不同行為,剛做的這些和策略設計模式相關,他讓你定義一簇算法(稱為 :策略),然后在運行時選擇一個算法。在這里,
算法族就是 ApplePredicate ,不同的策略就是 AppleHeavyWeightPredicate 和 AppleGreen-ColorPredicate 。
但是,該怎么利用 ApplePredicate 的不同實現呢?
你需要 filterApples 方法接受
ApplePredicate 對象,對 Apple 做條件測試。這就是行為參數化:讓方法接受多種行為(或戰
略)作為參數,并在內部使用,來完成不同的行為。
filter 方法看起來是這樣的:
“`java /** * 根據抽象條件進行篩選 * @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. 傳遞代碼/行為:
這里值得停下來小小地慶祝一下。這段代碼比我們第一次嘗試的時候靈活多了,讀起來、用
起來也更容易!現在你可以創建不同的 ApplePredicate 對象,并將它們傳遞給 filterApples
方法.
你已經做成了一件很酷的事: filterApples 方法的行為取決于你通過 ApplePredicate 對象傳遞的代碼。換句話說,你把 filterApples 方法的行為參數化了!
請注意,在上一個例子中,唯一重要的代碼是 test 方法的實現,如圖2-2所示;正是它定義
了 filterApples 方法的新行為。但令人遺憾的是,由于該 filterApples 方法只能接受對象,
所以你必須把代碼包裹在 ApplePredicate 對象里。你的做法就類似于在內聯“傳遞代碼”,因
為你是通過一個實現了 test 方法的對象來傳遞布爾表達式的
這就是說行為參數化是一個有用的概念的原因。你應該把它放進你的工具箱里,用來編寫靈
活的API
到此,我們覺得已經做的很好了,我們使用行為參數化解決了一些棘手的問題.
但是,目前來說,當要把新的行為傳遞給
filterApples 方法的時候,你不得不聲明好幾個實現 ApplePredicate 接口的類,然后實例化
好幾個只會提到一次的 ApplePredicate 對象。
Java有一個機制稱為匿名類,它可以讓你同時
聲明和實例化一個類。它可以幫助你進一步改善代碼,讓它變得更簡潔。但這也不完全令人滿意。它往往很笨重,因為它占用了很多空間。
“`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); }
現在暫時不用擔心這個新語法,下一章我們會詳細講解如何編寫和使用Lambda表達式。
線程就像是輕量級的進程:它們自己執行一個代碼塊。但是,怎么才能告訴線程要執行哪塊
代碼呢?多個線程可能會運行不同的代碼。我們需要一種方式來代表稍候執行的一段代碼。在
Java里,你可以使用 Runnable 接口表示一個要執行的代碼塊。請注意,代碼不會返回任何結果
(即 void ):
// java.lang.Runnable public interface Runnable{ public void run(); }
你可以像下面這樣,使用這個接口創建執行不同行為的線程:
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怎么通過行為參數化傳遞代碼”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。