资讯专栏INFORMATION COLUMN

通过行为参数化传递代码

Hanks10100 / 2333人阅读

摘要:行为参数化的好处在于我们可以把过滤的逻辑与应用过滤的行为解耦。实战第二章通过行为参数化传递代码读书笔记这是我第一篇文章,欢迎加入咖啡馆的春天。

应对不断变化的需求

在实际的工作中我们会将现实问题抽象成对象并对其进行处理,比如需要对一堆颜色和重量不同的苹果进行过滤分类。

1、苹果实体类

public class Apple {
    // 颜色
    private String color;
    // 重量
    private Integer weight;

    // Getter and Setter
}

2、过滤方法

    public static List filter(List appleList, String color, int weight) {
        // 符合条件的苹果集合
        List result = new ArrayList<>();
        for (Apple apple : appleList) {
            // 如果颜色和重量符合条件就存入
            if (color.equalsIgnoreCase(apple.getColor()) && weight == apple.getWeight()) {
                result.add(apple);
            }
        }
        return result;
    }

通过定制过滤方法,比如后期苹果可能会有其他的属性,是否成熟、产地等。我们可以在过滤方法的入参加上对应的属性并在内部进行判断。这就是通过修改过滤方法来 应对不断变化的需求。但这样有其局限性,如果需求不断地更改,那么就需要重写很多相似的方法。这违背了

DRY(Don"t Repeat Yourself)

的软件工程原则。

行为参数化

我们其实可以通过标准建模来定义一个过滤接口,让其比重写很多次过滤方法更好地 应对不断变化的需求

1、建立苹果谓词接口

// predicate:谓词,即一个返回 boolean 值的接口
public interface ApplePredicate {
    boolean test(Apple apple);
}

2、运用策略模式思想来构建具体算法(策略)实现

public class AppleColorPredicate implements ApplePredicate {
    @Override
    public boolean test(Apple apple) {
        // 选出绿色的苹果
        return "green".equalsIgnoreCase(apple.getColor());
    }
}

public class AppleWeightPredicate implements ApplePredicate {
    @Override
    public boolean test(Apple apple) {
        // 选出重量大于1的苹果
        return 1 < apple.getWeight();
    }
}

策略模式作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。

定义了一族算法(业务规则);

封装了每个算法;

这族的算法可互换代替(interchangeable)—— 策略模式 - 维基百科,自由的百科全书

我们可以将 AppleColorPredicateAppleWeightPredicate 看作是 过滤方法 的不同行为,需要 过滤方法 接收 ApplePredicate 对象对苹果进行过滤。这就是 行为参数化:让方法接收多种行为(或策略)作为参数,并在内部使用,来完成不同的行为。

1、修改过滤方法让其能够接收苹果谓词接口对象

    public static List filter(List appleList, ApplePredicate applePredicate) {
        // 符合条件的苹果集合
        List result = new ArrayList<>();
        for (Apple apple : appleList) {
            // 如果符合条件就存入
            if (applePredicate.test(apple)) {
                result.add(apple);
            }
        }
        return result;
    }

2、调用过滤方法进行过滤

public class Main {
    public static void main(String[] args) {
        List appleList = new ArrayList<>();

        Apple apple = new Apple();
        apple.setColor("red");
        apple.setWeight(1);
        appleList.add(apple);

        apple = new Apple();
        apple.setColor("green");
        apple.setWeight(2);
        appleList.add(apple);

        List result = filter(appleList, new AppleWeightPredicate());
    }
}

result 中就会只有重量大于1的苹果集合了。行为参数化 的好处在于我们可以把过滤的逻辑 boolean test() 与应用过滤的行为 public static List filter() 解耦。这样在需求不断更改时,只需要新增 ApplePredicate 实现再调用就行。

对付啰嗦

然而按照以上方式使用 ApplePredicate 依然有一个问题,那就是我们还是得不断地新增 ApplePredicate 的实现。本质上只是把重写过滤方法的代价转移到了新增谓词实现上。这个时候我们可以换一个思路出发,使用 匿名类 来随用随建谓词实现。

使用匿名类实现谓词接口

        List result = filter(appleList, new ApplePredicate() {
            @Override
            public boolean test(Apple apple) {
                // 选出绿苹果且重量为2
                return "green".equalsIgnoreCase(apple.getColor()) && 2 == apple.getWeight();
            }
        });

现在,我们只需要每次去匿名实现谓词接口就行,然而这样的写让人觉得很臃肿,而且看起来很让人费解。接下来看看 Lambda 是怎么让其变得简洁又友好的。

通过 Lambda 简化匿名实现

        List result = filter(appleList, (Apple apple1) -> "green".equalsIgnoreCase(apple1.getColor()) && 2 == apple1.getWeight());

是不是简洁得有点看不懂了?没关系,先细细品味,下一章我们会详细了解 Lambda。

我们还可以进一步抽象。目前 ApplePredicate 还只适用于苹果,而我想要其他对象进行过滤呢?可以使用泛型来定义需要处理的对象。

1、修改 ApplePredicate 成 Predicate

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

2、修改过滤方法

    public static  List filter(List list, Predicate predicate) {
        // 符合条件的集合
        List result = new ArrayList<>();
        for (T t : list) {
            // 如果符合条件就存入
            if (predicate.test(t)) {
                result.add(t);
            }
        }
        return result;
    }

这样我们就能将过滤方法用在其他对象上了。下一章我们会更加深入地理解 Lambda 是什么,能干什么。

Java 8 实战 第二章 通过行为参数化传递代码 读书笔记

这是我第一篇文章,欢迎加入咖啡馆的春天(338147322)。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/67606.html

相关文章

  • 《Java8实战》-读书笔记第二章

    摘要:但是到了第二天,他突然告诉你其实我还想找出所有重量超过克的苹果。现在,农民要求需要筛选红苹果。那么,我们就可以根据条件创建一个类并且实现通过谓词筛选红苹果并且是重苹果酷,现在方法的行为已经取决于通过对象来实现了。 通过行为参数化传递代码 行为参数化 在《Java8实战》第二章主要介绍的是通过行为参数化传递代码,那么就来了解一下什么是行为参数化吧。 在软件工程中,一个从所周知的问题就是,...

    Astrian 评论0 收藏0
  • 通过行为参数传递代码

    摘要:比如说,有个应用程序是帮助果农了解自己的库存。果农可能想有一个查找库存中所有绿色苹果的功能。又过了两天,果农又跑过来补充道要是我可以找出所有既是绿色,重量也超过克的苹果,那就太棒了。此外,类似的新功能实现起来还应该很简单,而且易于长期维护。 1 需求说明 在软件工程中,一个众所周知的问题就是,不管你做什么,用户的需求肯定会变。比如说,有个应用程序是帮助果农了解自己的库存。果农可能想有一...

    learn_shifeng 评论0 收藏0
  • Java 8th 函数式编程:lambda 表达式

    摘要:自定义函数式接口我们在前面例子中实现的苹果筛选接口就是一个函数式接口定义如下,正因为如此我们可以将筛选逻辑参数化,并应用表达式仅包含一个抽象方法,依照定义可以将其视为一个函数式接口。 Lambda 表达式是 java 8th 给我们带来的几个重量级新特性之一,借用 lambda 表达式可以让我们的程序设计更加简洁。最近新的项目摒弃了 6th 版本,全面基于 8th 进行开发,本文将探讨...

    luffyZh 评论0 收藏0
  • JSP第三篇【JavaBean的介绍、JSP的行为--JavaBean】

    摘要:不存在则实例化一个新的对象并将它以指定的名称存储到指定的域范围中。 什么是javaBean JavaBean就是一个普通的java类,也称之为简单java对象--POJO(Plain Ordinary Java Object),是Java程序设计中一种设计模式,是一种基于 Java 平台的软件组件思想 JavaBean遵循着特定的写法,通常有以下的规则: 有无参的构造函数 成...

    刘德刚 评论0 收藏0
  • Java8新特性总览

    摘要:新特性总览标签本文主要介绍的新特性,包括表达式方法引用流默认方法组合式异步编程新的时间,等等各个方面。还有对应的和类型的函数连接字符串广义的归约汇总起始值,映射方法,二元结合二元结合。使用并行流时要注意避免共享可变状态。 Java8新特性总览 标签: java [TOC] 本文主要介绍 Java 8 的新特性,包括 Lambda 表达式、方法引用、流(Stream API)、默认方...

    mayaohua 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<