【版本任你发】-5-只有一个函数的接口有用吗?

116 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情

0.背景

  话说啊,咱们快餐店老板因为瞎搞濒临破产,危难之际,虾搞一通餐饮有限公司收购了它。我们的程序员小孙开始了新的生活。

1.面向接口编程

  小孙因为得到老安的指点,学了两招以后,便喜欢上了学习。这一天,老安自由了。小孙也没注意到他,全身心在学习。

  因为老安到这一天,正好满135岁了,HR 给他过了个生日,说老安年龄大了,应该转到保安处看大门。老安拒绝了,他笑了笑,摆摆手:“算了吧,真遇到坏人,我这把老骨头,谁保护谁啊?”说完,他潇洒地离去了。

  花开两朵,各表一枝。小孙苦练起了面向接口编程,写出了一个这样的接口:

public interface YoungPersonService {
    
    boolean isYoung(int age);

}

  小黄笑话他:“就这么个东西还写个接口啊?真是画蛇添足,哈哈!”

  小孙生气了:“这是面向接口编程,你不懂!”

  小黄说:“什么面向接口编程,咱们还不是面向领导编程?领导就爱拍脑袋决策,咱们是面向拍脑袋编程,哈哈……”

  老罗听到了他们在吵闹,就问他们发生了什么。小孙和小黄一五一十地说了经过。老罗一边擦护手霜,一边说:“如果说一个接口,只有一个函数,确切来说只定义了一个抽象方法,那么,这就是函数式接口。小朋友们,函数式接口非常有用,它是 Lambda 表达式思想的前身”

2.函数式接口与 Lambda 表达式

Lambda表达式允许你直接以内联的形式为函数式接口的抽象方法提供实现,并把整个表达式作为函数式接口的实例(具体说来,是函数式接口一个具体实现的实例)。你用匿名内部类也可以完成同样的事情,只不过比较笨拙:需要提供一个实现,然后再直接内联将它实例化。——《Java实战》

  仔细想想,我们在书写 Lambda 表达式的时候,是不是只写了一个函数,就开始了处理?我们在写filter的条件时是不是也是直接就上手写了?好了,我们稍微改一下刚才的代码,然后做一个测试。为了减少学习恐惧感,我们还是 Predicate

  我们还是判断一个员工是否为年轻人:

public interface YoungPersonService extends Predicate<UserTests.User> {

}

  我们制作一个年轻员工的服务:

public class YoungEmployeeServiceImpl implements YoungPersonService {

    @Override
    public boolean test(UserTests.User user) {
        if (user == null) {
            return false;
        }
        if (user.getAge() < 35) {
            return true;
        }
        return false;
    }
}

  最后我们使用它:

public class UserTests {

    public static class User {

        private int age;

        public User(int age) {
            this.age = age;
        }

        public int getAge() {
            return age;
        }

        @Override
        public String toString() {
            return "User{" +
                    "age=" + age +
                    '}';
        }
    }

    public static void main(String[] args) {
        List<User> userList = new ArrayList<>();
        for (int i = 18; i <= 50; i++) {
            User user = new User(i);
            userList.add(user);
        }
        List<User> elders = userList.stream()
                .filter(new YoungEmployeeServiceImpl())
                .collect(Collectors.toList());
        System.out.println(elders);
    }

}

  小孙说:“这有点复杂,我看懵了。”老罗笑了笑:“别急,临时需求,我们用Lambda

public class UserTests {

    public static class User {

        private int age;

        public User(int age) {
            this.age = age;
        }

        public int getAge() {
            return age;
        }

        @Override
        public String toString() {
            return "User{" +
                    "age=" + age +
                    '}';
        }
    }

    public static void main(String[] args) {
        List<User> userList = new ArrayList<>();
        for (int i = 18; i <= 50; i++) {
            User user = new User(i);
            userList.add(user);
        }
        List<User> elders = userList.stream()
                .filter((user -> user.getAge() < 35))
                .collect(Collectors.toList());
        System.out.println(elders);
    }

}

  小孙和小黄都拍手叫好,感受到了简洁。

  小黄问老罗:“老罗,不说这个业务,你觉得什么算是年轻人?”老罗说:“年岁有加,并非垂老,理想丢弃,方堕暮年。”小孙和小黄又都拍手叫好,竖起大拇指,老罗不好意思地低下了头。

结语

  本例中,我们介绍了函数式接口以及Lambda表达式。这两种编程思维对于现代编程语言都非常重要,良好的设计可以为我们减少因需求变动而带来重构的次数。你还想到哪些应用呢?欢迎你在评论区和我讨论!