行爲參數化就是能夠幫助你處理頻繁變動的需求的一種軟件開發模式。一言以弊之,它意味着拿出一個代碼塊,把它準備好卻不去執行它。這個代碼塊之後能夠被你的程序的其餘部分調用,這意味着你能夠推遲這塊代碼的執行。算法
1、應對不斷變化的需求app
一、初試牛刀:篩選綠蘋果code
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); } }
二、再展身手:把顏色做爲參數對象
public static List<Apple> filterApplesByColor(List<Apple> inventory, String color){ List<Apple> result = new ArrayList<>(); for(Apple apple: inventory){ if(apple.getColor().equals(color)){ result.add(apple); } } return result; }
三、第三次嘗試:對你能想到的每一個屬性作篩選接口
public static List<Apple> filterApplesByColor(List<Apple> inventory, String color,int weight,boolean flag){ List<Apple> result = new ArrayList<>(); for(Apple apple: inventory){ if((flag &&apple.getColor().equals(color))|| (!flag &&apple.getWeight()>weight)){ result.add(apple); } } return result; }
2、行爲參數化開發
一、定義一個接口來對選擇標準建模(即定義一族算法),把它們封裝起來(稱爲「策略」),而後再運行時選擇一個算法。get
二、參數化:讓方法接收多種行爲(或戰略)做爲參數,並在內部使用,來完成不一樣的行爲。test
三、第四次嘗試:根據抽象條件篩選軟件
(1)傳遞代碼行爲List
public static List<Apple> filterApples(List<Apple> inventory, Predicate<Apple> p){ List<Apple> result = new ArrayList<>(); for(Apple apple : inventory){ if(p.test(apple)){ result.add(apple); } } return result; }
注: 正是test方法定義了filterApples方法的新行爲,但使人遺憾的是,因爲filterApples方法只能接收對象,因此你必須把代碼包裹在ApplePredicate對象裏。你的作法就相似於在內聯「傳遞代碼」,由於你是經過實現了test方法的對象來傳遞布爾表達式的。
(2)多種行爲,一個參數 正如咱們先前解釋的那樣,行爲參數化的好處在於你能夠把迭代要篩選的集合邏輯與對集合中每一個元素應用的行爲區分開來。
3、對付囉嗦
一、匿名類
二、第五次嘗試:使用匿名類
List<Apple> redApples2 = filter(inventory, new ApplePredicate() { public boolean test(Apple a){ return a.getColor().equals("red"); } }); System.out.println(redApples2); }
三、第六次嘗試:使用Lambda表達式
List<Apple> result = filterApples(inventory,(Apple apple)) -> "red".equles(apple.getColor())
四、第七次嘗試:將List類型抽象化
public static <T> List<T> filter(List<T> list,Predicate<T> p){ List<T> result = new ArrayList<>(); for(T e : list){ if(p.test(e)){ result.add(e); } } return result; }