JAVA 8 行为参数化

一、 行为参数化

通过将一个行为写成参数,再传进具体的执行代码中

举例来说: 你室友知道你要从校外回宿舍,他想让你帮他买写东西。这些东西可能是水,饭或者零食,水果,书等等。

这时你就有一个购买的行为。

这个购买的行为变成一个你回家过程中的一个参数,进行传递。那么,不过之后你室友怎么改变买的东西。你需要改变的只要购买这个行为,其他都可以不变。

二、主要作用:

为了应付需求的不断更改。

三、具体例子

例如:你给一个果农做了一个功能。这天,果农说他想筛选果子是苹果的数据。你这样写

public static List<Fruit> filterAppleFruit(List<Fruit> inventory){
    List<Fruit> result = new ArrayList<>();
    for (Fruit fruit:inventory) {
        // 筛选出是苹果的水果
        if ("apple".equals(fruit.getType())){
            result.add(fruit);
        }
    }
    return result;
}

又隔了一天,果农说:我想看看所有是香蕉的,行吗? 我:行!这时你咔咔改了下代码,变成这样

/**
 * 筛选水果
 * @param inventory 原水果数据
 * @param type 水果(香蕉  苹果...)
 * @return
 */
public static List<Fruit> filterTypeFruit(List<Fruit> inventory,String type){
    List<Fruit> result = new ArrayList<>();
    for (Fruit fruit:inventory) {
        // 筛选出是苹果的水果
        if (type.equals(fruit.getType())){
            result.add(fruit);
        }
    }
    return result;
}

使用时:

List<Fruit> appFruit = filterTypeFruit(inventory, "apple");
List<Fruit> bananaFruit = filterTypeFruit(inventory, "banana");

写完了,你感觉很棒,这回再改也不怕了。信心满满。结果第二天,果农说:这些水果要是能区分大小就好了,我想看看大于150克的数量。 我:...

没办法,继续吧~ 这时你就改了改,成功写完了。如下

/**
 * 仅筛选水果重量
 *
 * @param inventory 原水果数据
 * @param weight    水果重量
 * @return
 */
public static List<Fruit> filterWeightFruit(List<Fruit> inventory, int weight) {
    List<Fruit> result = new ArrayList<>();
    for (Fruit fruit : inventory) {
        // 筛选出是苹果的水果
        if (fruit.getWeight() > weight) {
            result.add(fruit);
        }
    }
    return result;
}

写完后,嗯... 看起来不错。需求都已经实现了。第二天,果农又来了,说:我想看看重量大于150克的苹果有多少,行吗?

我:儒雅随和.微笑。

没事,继续写吧~ 于是你写出了这样的代码

public static List<Fruit> filterFruits(List<Fruit> inventory, String color,
                                       int weight) {
    List<Fruit> result = new ArrayList<Fruit>();
    for (Fruit fruit : inventory) {
        if (fruit.getColor().equals(color) && fruit.getWeight() > weight) {
            result.add(fruit);
        }
    }
    return result;
}

使用:

List<Fruit> fruits = filterFruits(inventory, "banana",150);

这样,一个需求又完成了。但是作为一个有追求的程序员,上面的方法还是令人失望的,他打破了DRY(Don’t Repeat Yourself,不要重复自己)的软件工程原则。这样之后如果需要筛选颜色,日期等等需求时,都需要重复的去写一个方法。这也太槽糕了。

那么,如果使用行为参数化来实现呢?

上述的方法其实都是在进行筛选这个行为,筛选后返回true或者false的boolean值。那么我们可以先定义一个接口,来对应这个筛选的行为。接口如下:

public interface FruitPredicate{
    boolean test (Fruit apple);
}

那么现在你就可以通过FruitPredicate来实现不同的筛选标准了,如:

// 筛选重量大于150的
public class FruitHeavyWeightPredicate implements FruitPredicate{
    @Override
    public boolean test(Fruit fruit){
        return fruit.getWeight() > 150;
    }
}
// 筛选苹果的
public class FruitAppleTypePredicate implements FruitPredicate{
    @Override
    public boolean test(Fruit fruit){
        return "apple".equals(fruit.getType());
    }
}

上面是筛选的条件,筛选方法如下:

public static List<Fruit> filterFruits(List<Fruit> inventory,
                                       FruitPredicate p){
    List<Fruit> result = new ArrayList<>();
    for(Fruit fruit: inventory){
        if(p.test(fruit)){
            result.add(fruit);
        }
    }
    return result;
}

传入了筛选条件的抽象类,使用如下:

List<Fruit> redAndHeavyApples = filterFruits(inventory, new FruitAppleTypePredicate());

这个时候,已经很棒了~ filterFruits的方法取决于你通过FruitsPredicate对象传递的代码。换句话说,你把filterFruits的方法行为参数化了。

上述方法中,我们每次只需要更改或添加实现FruitsPredicate对象的类就可以了。从而达到多种行为(筛选行为)一个参数。从而达到你只使用一个方法,给它添加不同的行为来达到不同的目的或功能。

这时候可能有人又会觉得,这样每次实现一个需求,每次都得实现FruitsPredicate对象,然后再new再传入参数太麻烦,这时,你也可以使用匿名类。

如:

List<Fruit> appleApples = filterFruits(inventory, new FruitPredicate() {
    @Override
    public boolean test(Fruit fruit) {
        return "apple".equals(fruit.getType());
    }
});

或者使用 Lambda 表达式:

List<Fruit> appleApples = filterFruits(inventory, (FruitPredicate) fruit -> "apple".equals(fruit.getType()));

再将List类型抽象化:

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

public static List<T> filterFruits(List<T> inventory,
                                       Predicate<T> p){
    List<T> result = new ArrayList<T>();
    for(T t: inventory){
        if(p.test(t)){
            result.add(t);
        }
    }
    return result;
}

这时你就不仅仅局限于水果了,还可以是其他,如用户(User)

List<User> appleApples = filterFruits(inventory, (Predicate<User>) user -> "张三".equals(user.getName()));

在Java 8中,List自带了一个sort方法就是使用该方式实现的,有兴趣可以看看。

关于JAVA 8中的行为参数化到这里就差不多了。不知道你们悟了吗?以上所有的内容均出自JAVA 8实战这本书,有时间的小伙伴还是去看书比较好

只有自己写出来的,才是真正你自己的。那怕它一团槽

                                                                                     ----- 宝哥

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值