2.1 应对不断变化的需求


行为参数化是一种可以帮助处理频繁变更需求的软件开发模式。
例如,你为果农开发了一个苹果仓库程序。今天果农想查找仓库中的青苹果,明天他想查找重量在150克以上的苹果,后天他想查找既是青苹果重量又大于150克的苹果。
你可以写几个函数来实现这些功能,但这些函数总是要遍历苹果集合的。它们中的大部分代码都是相同的,只有一小段代码是不同的,理想上你只需要改动这一小段代码。
在Java8之前你可以使用匿名内部类+接口的方式来传递这段代码块,但这样很繁琐,而现在你可以更方便地处理这一过程。

这里有个苹果类

class Apple {  
    private String color;  
    private int weight;  
  
    public Apple(String color, int weight) {  
        this.color = color;  
        this.weight = weight;  
    }  
  
    public String getColor() {  
        return color;  
    }  
  
    public int getWeight() {  
        return weight;  
    }  
  
    @Override  
    public String toString() {  
        return "Apple{" +  
                "color='" + color + '\'' +  
                ", weight=" + weight +  
                '}';  
    }  
}

2.1.1 初试牛刀:筛选绿苹果


最简单的解决方案

public static List<Apple> findGreen(List<Apple> apples) {  
    List<Apple> list = new ArrayList<>();  
    for (Apple apple : apples) {  
        if ("green".equals(apple.getColor())) {  
            list.add(apple);  
        }  
    }  
    return list;  
}

那如果你要找黄色的呢,还要找绿色,蓝色,紫色的呢,你当然可以再写一些方法来解决这些问题但这并不是一个好办法。

2.1.2 再展身手:把颜色作为参数


一种简洁的做法是将颜色参数化,这样就能找到不同颜色的苹果了

public static List<Apple> findByColor(List<Apple> apples, String color) {  
    List<Apple> list = new ArrayList<>();  
    for (Apple apple : apples) {  
        if (color.equals(apple.getColor())) {  
            list.add(apple);  
        }  
    }  
    return list;  
}

但如果现在想找到重量大于150的苹果呢

public static List<Apple> findByWeight(List<Apple> apples, int weight) {  
    List<Apple> list = new ArrayList<>();  
    for (Apple apple : apples) {  
        if (weight <= apple.getWeight()) {  
            list.add(apple);  
        }  
    }  
    return list;  
}

这样也不错,但复制了大量代码来实现遍历库存,并对苹果应用筛选条件。
这打破了DRY(Don't Repeat Yourself, 不要重复自己)的软件工程原则,此时如果你想更改遍历方式来提升程序的性能,那么你需要更改大量的代码,这非常麻烦。

2.1.3 第三次尝试:为你能想到的每个属性做筛选


你现在要找到绿苹果并且重量大于150
下面给出两种笨拙的方法

List<Apple> target = findByColor(apples, "green");  
target = findByWeight(target, 150);

可以将之前的两个方法利用起来,但这样会两次遍历集合,性能不好。

public static List<Apple> findByWeightAndColor(List<Apple> apples, String color, int weight) {  
    List<Apple> list = new ArrayList<>();  
    for (Apple apple : apples) {  
        if (weight <= apple.getWeight() && color.equals(apple.getColor())) {  
            list.add(apple);  
        }  
    }  
    return list;  
}

这样看上去也还行,但如果筛选的条件变多,岂不是要写很多个这样的方法,这令人心碎。

现在你需要一种更好的方式来将苹果的筛选标准告诉findXXX方法,不要着急在下一节将会介绍行为参数化来实现这种灵活性。

下面是完整的代码

package lambdasinaction.chap1;  
  
import java.util.ArrayList;  
import java.util.List;  
  
class Apple {  
    private String color;  
    private int weight;  
  
    public Apple(String color, int weight) {  
        this.color = color;  
        this.weight = weight;  
    }  
  
    public String getColor() {  
        return color;  
    }  
  
    public int getWeight() {  
        return weight;  
    }  
  
    @Override  
    public String toString() {  
        return "Apple{" +  
                "color='" + color + '\'' +  
                ", weight=" + weight +  
                '}';  
    }  
}  
public class Test06 {  
    public static List<Apple> findGreen(List<Apple> apples) {  
        List<Apple> list = new ArrayList<>();  
        for (Apple apple : apples) {  
            if ("green".equals(apple.getColor())) {  
                list.add(apple);  
            }  
        }  
        return list;  
    }  
  
    public static List<Apple> findByColor(List<Apple> apples, String color) {  
        List<Apple> list = new ArrayList<>();  
        for (Apple apple : apples) {  
            if (color.equals(apple.getColor())) {  
                list.add(apple);  
            }  
        }  
        return list;  
    }  
  
    public static List<Apple> findByWeight(List<Apple> apples, int weight) {  
        List<Apple> list = new ArrayList<>();  
        for (Apple apple : apples) {  
            if (weight <= apple.getWeight()) {  
                list.add(apple);  
            }  
        }  
        return list;  
    }  
  
    public static List<Apple> findByWeightAndColor(List<Apple> apples, String color, int weight) {  
        List<Apple> list = new ArrayList<>();  
        for (Apple apple : apples) {  
            if (weight <= apple.getWeight() && color.equals(apple.getColor())) {  
                list.add(apple);  
            }  
        }  
        return list;  
    }  
  
    public static void main(String[] args) {  
        List<Apple> apples = new ArrayList<>();  
        apples.add(new Apple("red", 100));  
        apples.add(new Apple("yellow", 200));  
        apples.add(new Apple("green", 100));  
        apples.add(new Apple("green", 200));  
        List<Apple> green = findGreen(apples);  
        System.out.println("=================================");  
        System.out.println(green);  
        System.out.println("=================================");  
        List<Apple> target = findByColor(apples, "green");  
        target = findByWeight(target, 150);  
        System.out.println(target);  
        System.out.println("=================================");  
        target = findByWeightAndColor(apples, "green", 150);  
        System.out.println(target);  
    }  
}

程序的输出结果 :
=================================
[Apple{color='green', weight=100}, Apple{color='green', weight=200}]
=================================
[Apple{color='green', weight=200}]
=================================
[Apple{color='green', weight=200}]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值