zoukankan      html  css  js  c++  java
  • (二)行为化参数传递代码

    行为参数化就是可以帮助你处理频繁变更需求的一种软件开发模式。
    筛选苹果的例子:
    Apple 类

    @Getter
    @Setter
    public class Apple {
    
        private Integer weight;
    
        private String color;
        
    }
    

    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> 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;
        }
    

    这样就能满足筛选不同颜色苹果的需求了。满足这个需求之后,农民可能会想,要是能筛选出重苹果或者轻苹果就好了,大于150g的为重苹果,于是就有

        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;
        }
    

    这样做虽然满足了需求,但是却复制了大部分代码,他们仅有下面两句代码不同

        if ( apple.getColor().equals(color) ) {
                    result.add(apple);
        }
    
        if ( apple.getWeight() > weight ){
                    result.add(apple);
        }
    

    行为参数化

    到这里,你可能会想到农民可能会根据苹果的产地,苹果的采摘时间等等各种不同属性来进行筛选,于是索性抽象出一个filterApples的方法。而筛选的条件无非就是根据苹果的各种属性进行判断,然后返回一个boolean值,于是我们抽象出ApplePredicate接口

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

    现在你就可以用ApplePredicate的多个实现代表不同的选择标准了

        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());
            }
        }
    

    在这里我们抽象了ApplePredicate,每一种筛选就是一个策略,我们定义了筛选苹果的一族算法,把他们封装起来然后,然后在运行时选择一种算法,这就和策略模式相关联了。
    经过抽象之后我们的filterApples方法是这样的

    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;
        }
    

    到这里,当农民又提出新的需求,比如想要筛选出大于150g的红苹果,那么只需要实现ApplePredicate接口,然后传入filterApples就能满足需求了,这比之前的方式要灵活很多。这时filterApples方法的行为取决于你通过ApplePredicate对像传递的代码,也就是我们filterApples方法的行为参数化了。
    从上面的例子看比如筛选绿颜色苹果的类

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

    其实我们只关心的是返回boolean值部分的代码

        "green".equals(apple.getColor());
    

    而其他的代码都是实现一个接口的模板代码,都不是我们关心的,而通过lambda表达式我们就可以去掉那些臃肿的模板代码,像下面这样

        filterApples(inventory,apple -> "green".equals(apple.getColor()));
    

    抽象升级

    现在我们已经能够应对农民筛选苹果的需求了,但是当农民提出要对自家梨,橘子也有各种不同的筛选需求,此时我们不会有跟着将上面类似的代码写三遍,而是进行进一步的抽象,抽象成对一个列表根据不同条件进行筛选的方法,各种筛选条件就是不同的行为参数,于是就有了jdk里面stream的filter方法

    Stream<T> filter(Predicate<? super T> predicate);
    

    后面章节再介绍流
    像上面的例子就可以写成

    apples.stream().filter(apple -> "green".equals(apple.getColor()));
    

    这段代码的意思是通过通过apples获得一个流,然后利用filter方法对苹果进行筛选。
    类似于这样行为参数化的例子还有很多,他们结合lambda表达式会使得代码的编写变得更加简洁和优雅。通过抽象升级也使得代码更加灵活,易于扩展和维护,更加拥抱新的变化。

    注:内容参考至《java8实战》扫描下方二维码关注微信公众号,输入java8sz下载该书。CodeBooker

  • 相关阅读:
    Hive快速入门
    Spark Standalone 提交模式
    Spark WordCount 文档词频计数
    Spark Shuffle原理分析及性能优化
    Spark性能问题分析及优化【OOM、Stack Overflow】
    Redis常用命令【列表】
    Redis常用命令【字符串】
    Nosql数据库分类
    Redis内存数据库快速入门
    Scrapy实现腾讯招聘网信息爬取【Python】
  • 原文地址:https://www.cnblogs.com/vincili/p/9260681.html
Copyright © 2011-2022 走看看