Java8实战中理解行为参数化

        行为参数化就是就是一个方法接受多个不同的行为作为参数,并在内部使用它们,完成
不同行为的能力。比如开车出去再回来,可以传入取邮件这个参数,也可以传入买东西这个参数。再比如查找方法:那么参数可以是筛选重量大于150的,也可以传入参数筛选绿色的,也可以传重量既大于150,还是绿色的。

为理解行为参数化,首先准备苹果类(自己写的,也不在乎好不好用,能用就行)。

public class Apple {


    private String color;
    private float weight;

    enum Color
    {
        RED, GREEN, BLUE;
    }

    public Apple(String color, float weight) {
        this.color = color;
        this.weight = weight;
    }

    public String getColor() {
        return color;
    }
    public void setColor(String color) {
        this.color = color;
    }

    public float getWeight() {
        return weight;
    }

    public void setWeight(float weight) {
        this.weight = weight;
    }

    /**
     * 重写Apple类的toString
     * @return
     */
    @Override
    public String toString() {
        return "Apple{" +
                "color='" + color + '\'' +
                ", weight=" + weight +
                '}';
    }

    public static void main(String[] args){
        //应该有个库存,这个库存里存着很多苹果
        List<Apple> inventory = new ArrayList<>();
        initInventor(inventory);//初始化农场库存
        //使用遍历集合的方式取出绿色的苹果
        System.out.println("使用遍历集合的方式取出绿色的苹果:"+"\n");
        outInventor(filterGreenApples(inventory));
    }

    /**
     * 初始化存储苹果的仓库
     * @param inventory
     */
    private static void initInventor(List<Apple> inventory){
        Random r = new Random();
        Color[] colors = Color.values();
        for(int i = 0;i < 10; i++){
            Apple apple = new Apple(colors[r.nextInt(2)].toString(),r.nextFloat()*1);
            inventory.add(apple);
            System.out.println(apple.toString());
        }
    }

    /**
     * 输出包含苹果的集合
     * @param inventory
     */
    private static void outInventor(List<Apple> inventory){
        for(Apple apple:inventory){
            System.out.println(apple.toString());
        }
    }
}

step1:要筛选绿色的苹果,最初的写法:

 /**
     * 普通的筛选绿色的苹果
     * @param inventory
     * @return
     */
    public static 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;
    }

         坏处就是如果你要是筛选红色的你还得定义一个 filterRedApples(List<Apple> inventory)的方法,或者你定义一个filterApplesByColor(List<Apple> inventory,String color)的方法

step2:使用策略

        把策略(AppleGreenColorPredicate )传递给筛选方法:通过布尔表达式筛选封装在ApplePredicate对象内的苹果。

        进一步的我们定义一个接口,再用类进行实现这个接口,在筛选方法中将这个接口对象作为参数,这样这个接口肯定有相应行为,这样就相当于将行为参数化了。具体实现为:

接口的定义为:
public interface ApplePredicate {
    boolean test (Apple apple);
}

实现接口的类为:
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;
    }

Main函数中调用为

System.out.println("使用接口的方式取出绿色的苹果:"+"\n");
List<Apple> greenApples = filterApples(inventory, new AppleGreenColorPredicate());
outInventor(greenApples);

        唯一重要的代码是test方法的实现,正是它定义了filterApples方法的新行为。但令人遗憾的是,由于该filterApples方法只能接受对象,所以你必须把代码包裹在ApplePredicate对象里。你的做法就类似于在内联“传递代码”,因为你是通过一个实现了test方法的对象来传递布尔表达式的。

 step3:使用匿名类

        由于你为了实现一个接口而实体化了多个类,此时你可能会想到使用匿名内部类的方法来避免。

List<Apple> readApples = filterApples(inventory, new ApplePredicate() {
            @Override
            public boolean test(Apple apple) {
                return "RED".equals(apple.getColor());
            }
        });
outInventor(readApples);

匿名类:同时声明并实例化一个类,允许你随用随建。改善了为一个接口声明多个实体类的问题。

缺点是占用空间大。

step4:使用lambda表达式

这是在实现了filterApples的基础上实现。

//使用lambda表达式
System.out.println("使用lambda表达式");
List<Apple> result = filterApples(inventory,(Apple apple)->"RED".equals(apple.getColor()) && 0.15 < apple.getWeight());
outInventor(result);

step5:将List类型抽象化

构建接口

public interface Predicate<T> {
    boolean test(T t);
}

实现筛选方法

    //注意Predicate<T>是个类啊,因为我们筛选也是筛选的随便的一个水果类
    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;
    }

最后附上最终的代码:

Apple类

public class Apple {


    private String color;
    private double weight;

    enum Color
    {
        RED, GREEN, BLUE;
    }

    public Apple(String color, double weight) {
        this.color = color;
        this.weight = weight;
    }

    public String getColor() {
        return color;
    }
    public void setColor(String color) {
        this.color = color;
    }

    public double getWeight() {
        return weight;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }

    /**
     * 普通的筛选绿色的苹果
     * @param inventory
     * @return
     */
    public static 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 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;
    }
    //注意Predicate<T>是个类啊,因为我们筛选也是筛选的随便的一个水果类
    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;
    }

    /**
     * 重写Apple类的toString
     * @return
     */
    @Override
    public String toString() {
        return "Apple{" +
                "color='" + color + '\'' +
                ", weight=" + weight +
                '}';
    }

    public static void main(String[] args){
        //应该有个库存,这个库存里存着很多苹果
        List<Apple> inventory = new ArrayList<>();
        initInventor(inventory);//初始化农场库存
        //使用遍历集合的方式取出绿色的苹果
        System.out.println("使用遍历集合的方式取出绿色的苹果:"+"\n");
        outInventor(filterGreenApples(inventory));
        //使用接口的方式取出绿色的苹果
        System.out.println("使用接口的方式取出绿色的苹果:"+"\n");
        List<Apple> greenApples = filterApples(inventory, new AppleGreenColorPredicate());
        outInventor(greenApples);
        //使用接口实现的最好的打印方法
        prettyPrintApple(inventory, new AppleFancyFormatter());
        //使用匿名类来取所有红色苹果
        System.out.println("使用匿名类来取所有红色苹果");
        List<Apple> readApples = filterApples(inventory, new ApplePredicate() {
            @Override
            public boolean test(Apple apple) {
                return "RED".equals(apple.getColor());
            }
        });
        outInventor(readApples);
        //使用lambda表达式
        System.out.println("使用lambda表达式");
        List<Apple> result = filterApples(inventory,(Apple apple)->"RED".equals(apple.getColor()) && 0.15 < apple.getWeight());
        outInventor(result);
        //使用filter实现
        System.out.println("使用filter实现");
        result = filter(inventory,(Apple apple) -> "RED".equals(apple.getColor()));
        outInventor(result);
    }

    /**
     * 初始化存储苹果的仓库
     * @param inventory
     */
    private static void initInventor(List<Apple> inventory){
        Random r = new Random();
        Color[] colors = Color.values();
        for(int i = 0;i < 10; i++){
            Apple apple = new Apple(colors[r.nextInt(2)].toString(),r.nextDouble()*0.3);
            inventory.add(apple);
            System.out.println(apple.toString());
        }
    }

    /**
     * 输出包含苹果的集合
     * @param inventory
     */
    private static void outInventor(List<Apple> inventory){
        for(Apple apple:inventory){
            System.out.println(apple.toString());
        }
    }
    public static void prettyPrintApple(List<Apple> inventory,
                                        AppleFormatter formatter){
        for(Apple apple: inventory){
            String output = formatter.accept(apple);
            System.out.println(output);
        }
    }
}

AppleFormatter接口:

public interface AppleFormatter {
    String accept(Apple a);
}


Predicate接口:

public interface Predicate<T> {
    boolean test(T t);
}

ApplePredicate接口

public interface ApplePredicate {
    boolean test (Apple apple);
}


AppleFancyFormatter类

public class AppleFancyFormatter implements AppleFormatter{
    public String accept(Apple apple){
        String characteristic = apple.getWeight() > 0.15 ? "heavy" :
                "light";
        return "A " + characteristic +
                " " + apple.getColor() +" apple";
    }
}

AppleGreenColorPredicate实体类

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



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GallagherZ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值