Java JDK1.8 核心特性详解------行为参数化

行为参数化是一个很重要的概念。它代表着我们可以事先准备好可以实现不同功能的代码块,当需要时,将这个代码块作为参数传递给某个方法。通过行为参数化可以帮助我们应对需求不断变化的代码。下面将会通过很多代码解释行为参数化。


将代码作为参数传递

例如,你要实现一个在很多人中筛选符合条件的功能。这些人都具有名字(name),年龄(age),性别(sex )这三个属性。当要求按性别筛选人时,你可能会这么实现这个功能:

    public List<People> filterPeople(List<People> peopleList,String sex) {

        List<People> result = new ArrayList<>();
        for (People people : peopleList) {
            if (people.getSex().equals(sex)) {
                result.add(people);
            }
        }
        return result;
    }

当需求变化时,要求筛选大于指定年龄的人,于是,你又实现了一个新功能:

    public List<People> filterPeople(List<People> peopleList, Integer age) {

        List<People> result = new ArrayList<>();
        for (People people : peopleList) {
            if (people.getAge() >= age) {
                result.add(people);
            }
        }
        return result;
    }

但事情没有结束,如果需求一个同时筛选性别和年龄的方法,你可能要再添加一个新的方法:

    public List<People> filterPeople(List<People> peopleList, Integer age, String sex) {

        List<People> result = new ArrayList<>();
        for (People people : peopleList) {
            if (people.getAge() >= age && people.getSex().equals(sex)) {
                result.add(people);
            }
        }
        return result;
    }

这看起来好像很不错,但是又觉得很麻烦,因为你复制了很多重复的代码。这个时候,部分有经验的工程师可能会想到使用“策略设计模式”来应对需求不断变化的功能。定义一个接口,对筛选标准建模。

/**
 * 筛选标准建模
 */
public interface FilterPeople {

    boolean test(People people);
}

 通过实现这个接口,将不同的策略传给筛选方法,达到根据不同要求筛选人的要求。

      /**
     * 根据不同策略筛选人功能
     * @param peopleList 被筛选的人
     * @param filterPeople 筛选策略
     * @return 筛选结果
     */  
    public List<People> filterPeople(List<People> peopleList, FilterPeople filterPeople) {

        List<People> result = new ArrayList<>();
        for (People people : peopleList) {
            if (filterPeople.test(people)) {
                result.add(people);
            }
        }
        return result;
    }

当要求筛选性别为男性时:

public class FilterPeopleBySex implements FilterPeople {

    @Override
    public boolean test(People people) {

        return "男".equals(people.getName());
    }
}

当要求筛选年龄大于20时:


public class FilterPeopleByAge implements FilterPeople {
    
    @Override
    public boolean test(People people) {
        return people.getAge() >= 20;
    }
}

在需要的地方调用筛选方法:

        //查询男性
        List<People> man = filterPeople(peopleList, new FilterPeopleBySex());
        //查询大于20岁的人
        List<People> result = filterPeople(peopleList, new FilterPeopleByAge());

正如我们前面展示的,行为参数化能让我们把迭代的代码和不需要迭代的代码分开。这样我们可以重复使用同一个方法,然后给他不同的行为来达到不同的目的。跟之前的代码相比,现在只需要改变传入的策略就可以实现不同的功能。现在,filterPeople方法的功能取决于FilterPeople对象传递的代码(test方法中的代码)。换句话说,你把filterPeople方法的行为参数化了。但是,每次更换策略都要创建新的FilterPeople实现类,这真的很麻烦。我们需要改进一下上面的代码。我们想到可以使用匿名类,这样就可以不用创建新的类。

        //查询大于20岁的人
        List<People> result = filterPeople(peopleList, new FilterPeople() {

            @Override
            public boolean test(People people) {
                return people.getAge() >= 20;
            }
        });

        //查询男性
        List<People> man = filterPeople(peopleList, new FilterPeople() {

            @Override
            public boolean test(People people) {
                return "男".equals(people.getName());
            }
        });

 

//查询男性
List<People> man = filterPeople(peopleList, (People people)-> "男".equals(people.getName()));
//查询大于20岁的人
List<People> result = filterPeople(peopleList, (People people)-> people.getAge() >= 20);

Java API中很多方法都可以使用行为参数化,这些方法往往和匿名类一起使用,下面使用Comparator和Runnable进行演示。

例如对集合进行排序,在Java8 中,List自带了一个sort方法,通过传入不同的Comparator的实现来完成不通的排序:

//通过年龄排序
peopleList.sort(new Comparator<People>() {
     @Override
     public int compare(People p1, People p2) {
         return p1.getAge().compareTo(p2.getAge());
     }
});    

//通过名称排序
peopleList.sort(new Comparator<People>() {
     @Override
     public int compare(People p1, People p2) {
         return p1.getName().compareTo(p2.getName());
     }
});

这样子我们就可以简洁的根据需求编写排序代码。

对于Runnable,我们可以通过实现不同的run方法,执行不同的行为:

        //创建一个打印1的线程
        
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(1);
            }
        });

这样就不需要创建新的类,但是发现还是有一些重复的代码。而且你是通过传入不同FilterPeople对象来实实现,这有点类似于内联“代码传递”。在JDK1.8中,加入了Lambda表达式,可以将上面的代码简化为下面代码,这个跟前面的代码是完全等效的:

        //查询男性
        List<People> man = filterPeople(peopleList, new FilterPeopleBySex());
        //查询大于20岁的人
        List<People> result = filterPeople(peopleList, new FilterPeopleByAge());
        //按年龄排序
        peopleList.sort((p1, p2) -> p1.getAge().compareTo(p2.getAge()));
        //按姓名排序
        peopleList.sort((p1, p2) -> p1.getName().compareTo(p2.getName()));
        //创建线程
        Thread thread = new Thread(() -> System.out.println(1));

 

你会发现代码一下子就简洁了很多。现在只提出Lambda表达式,将会在下一篇详细的介绍Lambda的使用方法。


更多与JDK1.8相关的文章请看:Java JDK1.8 核心特性详解----(总目录篇)

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值