行为参数化传递代码
行为参数化是为了帮助我们应对不断变化的需求实现快速开发
比如在List<Apple> 苹果集合中我们需要实现:
- 找出绿色苹果
- 找出大苹果(重量大于500g)
- 找出绿色大苹果
对于这样的场景,我们可以将对集合的需求就可以抽象为一个行为。
假设场景:
1. 需要筛选绿苹果
public static List<Apple> filterGreenApples(List<Apple> inventory) {
List<Apple> result = new ArrayList<Apple>();
for(Apple apple: inventory){
if( "green".equals(apple.getColor() ) { //筛选绿色
result.add(apple);
}
}
return result;
}
- 需要筛选各种颜色(将颜色抽象为参数)
public static List<Apple> filterGreenApples(List<Apple> inventory) {
List<Apple> result = new ArrayList<Apple>();
for(Apple apple: inventory){
if( "green".equals(apple.getColor() ) {
result.add(apple);
}
}
return result;
}
-
需要大于500g的苹果或者绿苹果
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 result; }
这样确实比较蠢,不写注释的话,你能根据方法名判断flag是干啥的不?
这个时候我们就可以运用“ 行为参数化 ” 来帮我们解决问题。
首先我们来抽象需求:我们考虑的
是苹果,需要根据Apple的某些属性(比如它是绿色的吗?重量超过xxx克吗?)来返回一个
boolean值。我们把它称为谓词(即一个返回boolean值的函数)。让我们定义一个接口来对选
JDK中为我们提供了一个接口
public interface ApplePredicate{
boolean test (Apple apple);
}
现在我们可以根据不同需求实现不同的行为
public class AppleHeavyWeightPredicate implements ApplePredicate{
public boolean test(Apple apple){
return apple.getWeight() > 150; //筛选大于150g的
}
}
public class AppleGreenColorPredicate implements ApplePredicate{
public boolean test(Apple apple){
return "green".equals(apple.getColor()); //绿色的
}
}
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;
}
最终实现了行为参数化的fliterAppler方法看起来是不错的
public class AppleHeavyWeightPredicate implements ApplePredicate{
public boolean test(Apple apple){
return apple.getWeight() > 150;
}
}
public class AppleGreenColorPredicate implements ApplePredicate{
public boolean test(Apple apple){
return "green".equals(apple.getColor());
}
}
public class FilteringApples{
public static void main(String...args){
List<Apple> inventory = Arrays.asList(new Apple(80,"green"),
new Apple(155, "green"),
new Apple(120, "red"));
List<Apple> heavyApples =
filterApples(inventory, new AppleHeavyWeightPredicate());
List<Apple> greenApples =
filterApples(inventory, new AppleGreenColorPredicate());
}
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;
}
}
可是每次都还需要定义一个实现类再实例化,看起来好像十分的啰嗦。Java有一个机制称为匿名类,它可以让你同时
声明和实例化一个类。它可以帮助你进一步改善代码,让它变得更简洁。
下面的代码展示了如何通过创建一个用匿名类实现ApplePredicate的对象,重写筛选的例子:
List<Apple> redApples = filterApples(inventory, new ApplePredicate() {
public boolean test(Apple apple){
return "red".equals(apple.getColor());
}
});
但是不得不说匿名类真的很笨重,很多冗余的模版代码,而且还会有this指针的问题
引入Lambda我们可以做到这样子,避免了笨重了匿名类。
List<Apple> result =
filterApples(inventory, (Apple apple) -> "red".equals(apple.getColor()));