一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第22天,点击查看活动详情。
前言
现在的大多数JDK版本就是使用的JDK 8,我自己也不例外,对于JDK 8以上的版本,有去了解一些对比的功能差异,以及更新的功能,这些更新的功能在我自己看来,都是一些比较基础化的更新或者是说跟前一个版本没有那么重大的更新,所以JDK 8在很长的一段时间在国内还是主流的开发版本,但是我们还是要去学习使用最新的长期支持版的,比如截止本文发布前的最新的长期支持版是JDK 17。那么我们今天就正式步入今天的主题——Java行为参数化解析。
Java行为参数化说明
假设我们现在有一个这样的需求场景,有一个水果经销商,他负责销售各种各样的水果,他想要把红色的苹果找出来都有哪些。这时候你会怎么做呢?苹果的对象属性如下:
public class Apple {
private Color color;
private Integer weight;
public enum Color {
GREEN,RED;
}
}
大多数人的第一想法就是进行集合的遍历循环,然后进行颜色判断,查找出红色苹果的集合进行返回。代码块可能编写的像下面这样:
public List<Apple> filterApples(List<Apple> apples) {
List<Apple> redApples = new ArrayList<>();
for (Apple apple : apples) {
if (Apple.Color.RED.equals(apple.getColor())) {
redApples.add(apple);
}
}
return redApples;
}
但是这样子的代码会产生什么问题呢?假如说用户的需求变化了,他想要红色苹果,你把颜色作为参数进行传递。那么他后面的需求又变了,想要大于150克的苹果呢,想要小于120克的苹果并且是绿色的。想要原产地是福建的并且是红色的苹果呢...用户的思维和他的用户场景会让他产生各种各样需求,如果你还是不断的添加参数进行传递,各种各样的if判断,代码将变得非常的长,有错误的话也无法调试的。那么这时候你可能会想到这种需求变化的条件下应该可以运用软件工程的设计模式进行解决的。没错的,我们来观察一下对苹果过滤的代码,主要的逻辑如下:
- 迭代苹果的集合。
- 对每个苹果进行某个条件判断。
- 返回符合条件的苹果集合。 如果我们将上面的各种需求,按照每个需求都使用一个方法实现。那么实现这些方法的过程中,第一点和第三点。是不是都是一致的,这时候我们就可以对第二点进行选择标准的建模,定义如下接口:
public interface ApplePredicate {
boolean test(Apple apple);
}
这个接口的含义就是我们传递一个苹果进去,然后进行某种条件的判断后,返回是否满足该条件的结果。这个表述非常符合我们第二点。这时候,我们就可以将filterApples的方法修改成如下代码:
public List<Apple> filterApples(List<Apple> apples, ApplePredicate predicate) {
List<Apple> redApples = new ArrayList<>();
for (Apple apple : apples) {
if (predicate.test(apple) {
redApples.add(apple);
}
}
return redApples;
}
使用这样的形式,我们可以实现各种条件ApplePredicate的实现类,将判断的条件通过对象,也就是行为作为参数,传递进方法。这样我们就不需要根据客户的需求不断变化。去不断的修改,调整我们的方法参数和增加代码块各种判断,最后导致代码无法维护的地步。
通过对选择标准进行建模,多个ApplePredicate的多个实现就代表了多个选择标准,这些标准可以看作是filterApples的不同行为的。这个跟我们的“策略设计模式”相关,定义一族的算法,封装为策略。然后在运行时选择相应的策略。例如筛选重苹果策略AppleHeavyWeightPredicate和筛选绿苹果策略AppleGreenColorPredicate。使用filterApples方法接受ApplePredicate对象。对Apple对象进行测试。这就是行为参数化。让方法接受多种行为(策略)作为参数在内部使用。完成不同的行为。将filterApples方法迭代集合的逻辑和应用到集合的每个元素的行为(这里是一个谓词)区分开。
总结
通过阅读本文后,如果你对行为参数化有一定的理解了,那么这将对于你学习Java的Lambda语法会有很大的帮助的。