我们需要从一堆苹果中按颜色挑出符合要求的苹果。最初,我们可能会按不同的条件写几个相似的方法来做这件事
- Version 1
public List<Apple> filterGreenApples(List<Apple> inventory){
List<Apple> result = new ArrayList<>();
for(Apple apple: inventory){
if("green".equals(apple.getColor())){
result.add(apple);
}
}
return result;
}
public List<Apple> filterRedApples(List<Apple> inventory){
List<Apple> result = new ArrayList<>();
for(Apple apple: inventory){
if("red".equals(apple.getColor())){
result.add(apple);
}
}
return result;
}
好像重复的代码有点太多了,只有颜色的判断条件不同而已,我们做一个重构
- Version 2
public 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;
}
单单颜色不能满足我们的需求,我们还希望按重量来过滤
- Version 3
public List<Apple> filterApplesBiggerThanWeight(List<Apple> inventory, int weight){
List<Apple> result = new ArrayList<>();
for(Apple apple: inventory){
if(apple.getWeight() > weight ){
result.add(apple);
}
}
return result;
}
颜色版本和重量版本差的只是判断条件,其他部分依然是相同的,同理对其他属性来说情况也是一样的,所以我们引入行为参数化。
- Version 4
public interface ApplePredicate{
public boolean test(Apple apple);
}
public List<Apple> filterApples(List<Apple> inventory, ApplePredicate p){
List<Apple> result = new ArrayList<>();
for(Apple apple: inventory){
if(p.test() ){
result.add(apple);
}
}
return result;
}
public AppleGreenColorPredicate implements ApplePredicate{
public boolean test(Apple apple){
return "green".equals(apple.getColor());
}
}
public AppleWeightPredicate implements ApplePredicate{
public boolean test(Apple apple){
return apple.getWeight() > 150;
}
}
行为参数化解决了我们的主要问题,但是实现看起来有点啰嗦,我们要实现AppleGreenColorPredicate,AppleWeightPredicate等等,有许多重复的类定义代码。Java 7时代我们使用匿名类来减少一部分代码
- Version 5
List<Apple> redApples = filterApples(inventory, new ApplePredicate() {
public boolean test(Apple apple){
return "red".equals(apple.getColor());
}
}
到了Java 8我们可以使用Lambda来替代不易使用的匿名类
- Version 6
List<Apple> redApples = filterApples(inventory, apple -> "red".equals(apple.getColor()))
这样就简洁很多了。