本人Java8系列博客全是对< Java8实战 >,这本书的总结,不是代码生产者,只是个勤劳的搬运工.
相比枯燥的概念,本人更愿意通过实际例子说明.
需求1
需求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;
}
需求2
需求2:想要筛选多种颜色:浅绿色、暗红色、黄色等,上述方法就应付不了了。一个良好的原则是在编写类似的代码之后,尝试将其抽象化。可以将颜色当做参数传入.
//改进::把颜色作为参数
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 result;
}
需求3
需求3: 要是能区分轻的苹果和重的苹果就太好了。重的苹果一般是重量大于150克
public static List<Apple> filterApplesByWeight(List<Apple> inventory, int weight) {
List<Apple> result = new ArrayList<Apple>();
for (Apple apple : inventory) {
if (apple.getWeight() > weight) {
result.add(apple);
}
}
return result;
}
这时我们会发现,这段代码与需求1的代码几乎是一样的,有点儿令人失望,因为它打破了DRY(Don’t Repeat Yourself,不要重复自己)的软件工程原则,接下来引出:行为参数化 解决上述问题 这种做法类似于策略设计模式
代码改进1:
//抽象化接口
public interface ApplePredicate {
boolean test(Apple apple);
}
public static List<Apple> filterApples(List<Apple> inventory, ApplePredicate p) {
List<Apple> result = new ArrayList<Apple>();
for (Apple apple : inventory) {
if (p.test(apple)) {
result.add(apple);
}
}
return result;
}
public static void main(String[] args) {
filterApples(new ArrayList<Apple>(), new ApplePredicate() {
@Override
public boolean test(Apple apple) {
return apple.getWeight() > 150;
}
});
}
*这里值得停下来小小地庆祝一下。这段代码比我们第一次尝试的时候灵活多了,读起来、用起来也更容易!现在你可以创建不同的ApplePredicate对象,并将它们传递给filterApples方法。免费的灵活性!比如,如果农民让你找出所有重量超过150克的红苹果,你只需要创建一个类来实现ApplePredicate就行了。你的代码现在足够灵活,可以应对任何涉及苹果属性的需求变更了.
代码改进2:匿名内部类毕竟啰嗦,使用Lambda 表达式简化
public static void main(String[] args) {
filterApples(new ArrayList<Apple>(), (Apple apple) -> "red".equals(apple.getColor()));
}
代码改进3: * 在通往抽象的路上,我们还可以更进一步。目前,filterApples方法还只适用于Apple(如何适应其他水果呢?) 你还可以将List类型抽象化,从而超越你眼前要处理的问题:
public interface ApplePredicate<T> {
boolean test( T t);
}
public static <T> List<T> filterApples(List<T> inventory, ApplePredicate<T> p) {
List<T> result = new ArrayList<T>();
for (T t : inventory) {
if (p.test(t)) {
result.add(t);
}
}
return result;
}
public static void main(String[] args) {
//使用泛型
//好了,现在对象可以不只是apple了,对于其他水果也同样适用
filterApples(new ArrayList<>(), (Apple apple) -> "red".equals(apple.getColor()));
}
经过一系列改进后代码,相对一开始是不是可以满足不同的客户需求…