李文軒 2019-04-20
行為參數(shù)化的目的是“應(yīng)對(duì)不斷變化的需求“尤揣;在需求發(fā)生改變時(shí),用行為參數(shù)化策略可以保持軟件自身的框架不變,但改變業(yè)務(wù)邏輯的行為男旗。
全文用
Apple
篩選的例子體現(xiàn)不同策略的情況
不用行為參數(shù)化的方案:
1. 不考慮需求變化的情況 (書(shū) 2.1.1)
- 在不考慮需求變化的情況下,只按照初始需求編程
- 這里會(huì)從輸入的List里篩選出
color
是"green"
的Apple
- 缺點(diǎn):
- 不能夠應(yīng)對(duì)需求變化:如果需求改變到篩選出
"red"
欣鳖,簡(jiǎn)單的方法是復(fù)制這個(gè)方法然后新建一個(gè)filterRedApples
的方法察皇。
- 不能夠應(yīng)對(duì)需求變化:如果需求改變到篩選出
//篩選出綠色的蘋(píng)果
public static List<Apple> filterGreenApples(List<Apple> inventory){
List<Apple> result = new ArrayList<>();
for(Apple apple: inventory){
//檢查蘋(píng)果的顏色是否是綠色,若是則添加到result
if( "green".equals(apple.getColor()) ){
result.add(apple);
}
}
return result;
}
2. 通過(guò)把顏色作為參數(shù)的方法 (書(shū) 2.1.2)
- 若是簡(jiǎn)單應(yīng)對(duì)篩選不同顏色的需求泽台,我們可以將需要篩選的顏色作為參數(shù)
- 通過(guò)傳遞不同的顏色來(lái)應(yīng)對(duì)不同顏色的篩選
- 缺點(diǎn):
- 不夠靈活:若需求再度改變什荣,同樣是篩選,可是是按重量篩選怀酷,而不是顏色的話稻爬,簡(jiǎn)單的方法是復(fù)制這個(gè)方法然后新建一個(gè)
filterApplesByWeight
的方法。
- 不夠靈活:若需求再度改變什荣,同樣是篩選,可是是按重量篩選怀酷,而不是顏色的話稻爬,簡(jiǎn)單的方法是復(fù)制這個(gè)方法然后新建一個(gè)
//用輸入的顏色參數(shù)篩選蘋(píng)果
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;
}
//用輸入的重量參數(shù)篩選蘋(píng)果
public static List<Apple> filterApplesByWeight(List<Apple> inventory, int weight){
List<Apple> result = new ArrayList<>();
for(Apple apple: inventory){
if(apple.getWeight() > weight){
result.add(apple);
}
}
return result;
}
3. 用一個(gè)方程來(lái)應(yīng)對(duì)多個(gè)屬性的篩選 (書(shū) 2.1.3)
- 把作為篩選條件的顏色和重量同時(shí)通過(guò)參數(shù)傳遞蜕依,并用一個(gè)旗幟來(lái)表示用顏色或者重量來(lái)篩選
- 在調(diào)用方法時(shí)桅锄,傳遞的顏色和重量其中一個(gè)將沒(méi)有意義。(若用顏色來(lái)篩選样眠,重量的參數(shù)將沒(méi)有意義友瘤,反之亦然)
- 缺點(diǎn):
- 有些參數(shù)意義不明:這里意義不明的是
flag
,這個(gè)參數(shù)名降低了代碼的可讀性 - 不夠靈活:還是局限于
color
和weight
兩個(gè)屬性 - 代碼變得臃腫:若同時(shí)使用多個(gè)篩選條件檐束,這種方法用起來(lái)不方便
- 有些參數(shù)意義不明:這里意義不明的是
//flag代表采用什么標(biāo)準(zhǔn)來(lái)篩選蘋(píng)果辫秧,true則用顏色,false則用重量
public static List<Apple> filterApples(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;
}
用行為參數(shù)化的方案:
- 函數(shù)接口
- 用一個(gè)函數(shù)接口來(lái)定義篩選標(biāo)準(zhǔn)
- 這里我們是通過(guò)一個(gè)布爾值來(lái)決定是否可以通過(guò)篩選被丧,所以我們可以用一個(gè)謂詞(Predicate)接口來(lái)抽象我們的篩選標(biāo)準(zhǔn)盟戏。
public interface ApplePredicate{
boolean test (Apple apple);
}
- 實(shí)現(xiàn) 篩選標(biāo)準(zhǔn)/行為
//選出重的蘋(píng)果
class AppleHeavyWeightPredicate implements ApplePredicate{
@Override
public boolean test(Apple apple) {
return apple.getWeight() > 150;
}
}
//選出綠色的蘋(píng)果
class AppleGreenColoPredicate implements ApplePredicate{
@Override
public boolean test(Apple apple) {
return "green".equals(apple.getColor());
}
}
- 改變
filterApples
方法使其接受ApplePredicate
的對(duì)象,從而引入篩選的條件晚碾。- test方法的實(shí)現(xiàn)決定了篩選標(biāo)準(zhǔn)/行為抓半。
public static List<Apple> filterApples(List<Apple> inventory, ApplePredicate p){
List<Apple> result = new ArrayList<>();
for(Apple apple:inventory){
if(p.test(apple)){
result.add(apple);
}
}
return result;
}
- 使用篩選標(biāo)準(zhǔn)
- 不使用
Lambda
表達(dá)式的情況
filterApples(inventory, new AppleGreenColoPredicate());
filterApples(inventory, new AppleHeavyWeightPredicate());
- 使用
Lambda
的情況 - 優(yōu)點(diǎn):
- 增加可讀性
//針對(duì)只用一次的標(biāo)準(zhǔn)/行為
filterApples(inventory, (Apple apple) -> "green".equals(apple.getColor()));
filterApples(inventory, (Apple apple) -> apple.getWeight() > 150);
- 若需要復(fù)用篩選標(biāo)準(zhǔn)/行為
//Lamdba 復(fù)用
//聲明和定義 篩選標(biāo)準(zhǔn)/行為
ApplePredicate appleGreenColorPredicate = (Apple apple) -> "green".equals(apple.getColor());
ApplePredicate appleHeavyWeightPredicate = (Apple apple) -> apple.getWeight() > 150;
filterApples(inventory, appleGreenColorPredicate);
filterApples(inventory, appleHeavyWeightPredicate);
- 篩選的標(biāo)準(zhǔn)/行為獨(dú)立于
filterApple
方法外,需要新的標(biāo)準(zhǔn)/行為時(shí)格嘁,可以獨(dú)立編寫(xiě) -
filterApples
方法改變后笛求,我們可以根據(jù)需求,變換我們傳遞的標(biāo)準(zhǔn)/行為來(lái)用不同的標(biāo)準(zhǔn)篩選糕簿。這樣可以保持框架(filterApples
)不變探入。
Reference:
- Fusco, Mario, and Alan Mycroft. Java 8 in Action: Lambdas, Streams, and Functional-Style Programming. Manning, 2015.