1|0概述
通常,传递给方法的数据不同,结果也不同。同样的,如果我们希望方法被调用时的行为不同,该怎么做呢?结论是:只要能将代码传递给方法,那么就可以控制方法的行为。
说得再具体点,过去我们总是创建包含所需行为的对象,然后将对象传递给想要控制的方法,一般使用匿名内部类来实现。假设现在有这么一个需求:有一个员工信息列表,根据年龄过滤出符合条件的员工信息
// 过滤出大于35岁的员工
public List<Employee> filterEmployee(List<Employee> list) {
List<Employee> emps = new ArrayList<>();
for(Employee emp : list) {
if(emp.getAge() > 35) {
emps.add(emp);
}
}
return emps;
}
// 过滤出大于45岁的员工
public List<Employee> filterEmployee2(List<Employee> list) {
...
}
这样写当然能实现需求,但如果需求变了,要过滤 45 岁的,那岂不是又得写一个 filterEmplyee2() 方法?如果还要过滤 50 岁的,60 岁的,那就没完没了了,而且代码的实现逻辑几乎没有区别。于是我们借助策略模式的思想来简化代码。
public interface MyPredicate<> {
boolean predicate(T t);
}
// 如果有其他过滤需求,只需要实现 MyPredicate 接口即可
public class EmployeeFilter implements MyPredicate<Employee> {
@Override
public boolean predicate(Employee employee) {
return t.getAge() >= 35;
}
}
// 根据传入的 MyPredicate 对象来实现不同的过滤逻辑
public List<Employee> filterEmployee(List<Employee> list, MyPredicate<Employee> mp) {
List<Employee> emps = new ArrayList<>();
for(Employee emp : list) {
if(mp.predicate(emp)) {
emps.add(emp);
}
}
return emps;
}
public void test(List<Employee> list) {
// 创建实现类对象,传入过滤方法
MyPredicate<Employee> predicate = new EmployeeFilter<>();
List<Employee> res = filterEmployee(list, predicate);
// 更简单的方式是使用匿名内部类
List<Employee> res2 = filterEmployee(list, new MyPredicate<Employee>() {
@Override
public boolean predicate(Employee employee) {
return t.getAge() >= 100;
}
});
}
通过观察我们发现,我们需要的只有 predicate() 方法的代码,其他的我们一律不关心。如果 MyPredicate 接口还有其他抽象方法,我们又必须每一个做一次实现,但真正用上的只有 predicate() 方法,不仅显得冗余,而且可读性也很低。为了解决这个问题,Java8 为我们提供了 Lambda 表达式和方法引用两种更加简洁的方式。
2|0Lambda 表达式
Lambda 表达式是一个匿名函数,可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样传递)。虽然在