Java8实战—通过行为参数化传递代码

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_22797429/article/details/82320747

目录

序言

接触Java8一段时间了,发现这东西确实很好,公司许多大牛也都在用,买了一本书《Java8实战》,阅读书中的一些内容做点学习笔记。

初试牛刀:筛选绿苹果

第一个解决的问题可能是下面这样的:

    public static List<Apple> filterGreenApples(List<Apple> inventory){
        List<Apple> result = new ArrayList<Apple>();
        for(Apple apple: inventory){
            if("greeen".equals(apple.getColour())){
                result.add(apple);
            }
        }
        return result;
    }

上面这个是我们要筛选出绿苹果的程序,需求是在时刻变化的嘛!现在农民改变主意了,想要筛选出其他颜色的苹果,如浅绿色、暗红色、黄色等。那我们首先想到的是将其抽象化。

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

当需求变更时,我们首先想到的是将颜色作为参数,然后灵活的适应变化:

public static List<Apple> filterGreenApples(List<Apple> inventory, String colour){
        List<Apple> result = new ArrayList<Apple>();
        for(Apple apple: inventory){
            if(colour.equals(apple.getColour())){
                result.add(apple);
            }
        }
        return result;
    }

这下就可以通过颜色来筛选出符合要求的苹果啦,那么现在农民需要筛选出重量大于150g的苹果,该怎么实现呢?你可能会想到这样来实现:

public static List<Apple> filterGreenApples(List<Apple> inventory, long weight){
        List<Apple> result = new ArrayList<Apple>();
        for(Apple apple: inventory){
            if(apple.getWeight() > weight){
                result.add(apple);
            }
        }
        return result;
    }

这样确实也满足了需求,但是复制了大量的代码,不符合软件的工程原则,那么你可以增加一个标志位的方式来区分颜色和重量的查询。于是你想到了下面的这种方式:

第三次尝试:对你想到的每一个属性做筛选

public static List<Apple> filterGreenApples(List<Apple> inventory, String colour, long weight, boolean flag){

        List<Apple> result = new ArrayList<Apple>();
        for(Apple apple: inventory){
            if((flag&&apple.getWeight() > weight)||
                    (!flag&&apple.getColour().equals(colour))){
                result.add(apple);
            }
        }
        return result;
    }

这样你就可以通过一个方法来控制两个属性的筛选了,是不是感到很机智?但是这让程序看起来很笨拙,如果农民需要筛选出大小、形状、产地。怎么办呢?在下一节,我们将利用行为参数化来实现这种灵活性。

行为参数化

我们首先想到的是定一个接口来对选择标准进行建模:

interface ApplePredicate{
    boolean test(Apple apple);
}

class AppleHeavyWeightPredicate implements ApplePredicate{
    public boolean test(Apple apple) {
        return apple.getWeight() >150;
    }
}

class AppleGreenColorPredicate implements ApplePredicate{
    public boolean test(Apple apple) {
        return "green".equals(apple.getColour());
    }
}

上面所做的操作和“策略设计模式”相关,让方法接收多种行为作为参数,并在内部使用来完成不同的行为。

根据抽象条件筛选

    public class GreenApple {

    public static List<Apple> filterApples(List<Apple> inventory, ApplePredicate p){

        ArrayList<Apple> result = new ArrayList<>();
        for(Apple apple: inventory){
            if(p.test(apple)){
                result.add(apple);
            }
        }
        return result;
    }

    public static class AppleRedAndHeavyPredicate implements ApplePredicate{

        @Override
        public boolean test(Apple apple) {
            return "red".equals(apple.getColour())&&apple.getWeight() > 150;
        }
    }

    public static void main(String[] args) {

        Apple apple = new Apple();
        apple.setColour("green");
        apple.setWeight(12);

        Apple apple2 = new Apple();
        apple2.setColour("red");
        apple2.setWeight(288);

        ArrayList<Apple> inventory = new ArrayList<Apple>();
        inventory.add(apple);
        inventory.add(apple2);

        List<Apple> apples = GreenApple.filterApples(inventory, new AppleRedAndHeavyPredicate());

    }
}

通过这种方式,农民只需创建一个类来实现ApplePredicate接口就行了,你可以在这个类里面定义你想筛选的规则,这样就可以将filterApples方法的行为参数化了。

匿名内部类

List<Apple> redApples = filterApples(inventory, new ApplePredicate() {
            @Override
            public boolean test(Apple apple) {
                return "red".equals(apple.getColour());
            }
        });

虽然这样也可以,但是会显的程序很笨拙

使用Lambda表达式

使用Lambda表达式会让程序看起来很干净整洁

            List<Apple> result=filterApples(inventory,(Apple apple1) ->"red".equals(apple1.getColour()));

甚至可以省略Apple类型,因为它只有一个方法

        List<Apple> result=filterApples(inventory,apple1 ->"red".equals(apple1.getColour()));

将List类型抽象化

在通往抽象的路上,其实我们可以做到更好!你可以将List类型抽象化,从而超越你目前想处理的问题

List<Apple> redApple = filter(inventory, (Apple apple) -> "red".equals(apple.getColour()));
        List<String> str = filter(numbers, (Integer i) -> i % 2 == 0);
public static  <T>List<T> filter(List<T> list, Predicate<T> p){
        List<T> result = new ArrayList<>();
        for(T e:list){
            if(p.test(e)){
                result.add(e);
            }
        }
        return result;
    }

小结

行为参数化:就是一个方法接受多个不同的行为作为参数,并在内部使用它们,完成不同行为的能力
传递代码:就是将新行为作为参数传递给方法

猜你喜欢

转载自blog.csdn.net/sinat_22797429/article/details/82320747
今日推荐