java8新特性--函数式接口

工作这么久了,也是最近半年才注意到java.util.function。以前都完全没有使用过这个包,因此当第一次看见这个的时候就比较蒙圈。原谅我的寡闻。

我也是网上百度了一下。

https://blog.csdn.net/weixin_43415201/article/details/109957738https://blog.csdn.net/weixin_43415201/article/details/109957738网上讲得其实也算比较透彻。

接口

总结来说有四个接口。

Function:通俗理解为具体执行方法的执行体

表示接受一个参数并生成结果的函数。并且核心的方法是apply方法,表示执行。

Consumer:消费者。通俗理解为拿到数据后需要执行的操作。

 表示接受单个输入参数但不返回结果的操作。与大多数其他功能接口不同,消费者需要通过另一侧进行操作。

Supplier:供给者。提供数据的一方。

Predicate:用于测试一个方法。返回true或false。

 通过这四个接口可以发现,其思想与消息中间件有类似之处。都有消息提供者和消息消费者模式,但是不同的是,这里并不算是异步的,Supplier只是提供了一个存储值的功能。而consumer则是提供了一个执行定义方法的功能。且consumer是void方法。分开使用也可。其实主要还是用于抽象统一。

应用

那有没有什么比较好的应用呢?

有。那就是模板模式。

假设纯牛奶和特仑苏的生产工序基本一样,但是某个来源和关键步骤是不同的。那么应该是什么样的代码呢?

首先要定义一个模板类。

package com.xq.traditonal.impl;

/**
 * 牛奶制作抽象类
 */
public abstract class AbstractProcess {
    // 牛奶工序流程
    public String execute(){
        String f = commonHandle();
        String sec = specialHandle(f);
        return assemble(sec);
    }
    // 组装处理
    private String assemble(String sec) {
        return sec + " 组装完成\n";
    }
    // 公共处理
    private String commonHandle() {
        return "通用处理一。\n" ;
    }
    // 特殊处理
    abstract String specialHandle(String source);
}

然后继承模板类定义各自的具体逻辑。

package com.xq.traditonal.impl;

/**
 * 纯牛奶
 */
public class PureMilk extends AbstractProcess{
    private String name;

    public PureMilk() {
        name = "纯牛奶";
    }
    @Override
    String specialHandle(String source) {
        return source + name + "杀菌+消毒+防腐剂。\n";
    }
}
package com.xq.traditonal.impl;

/**
 * 特仑苏
 */
public class Terentsu extends AbstractProcess{
    private String name;

    public Terentsu() {
        name = "特仑苏";
    }
    @Override
    String specialHandle(String source) {
        return source + name + "杀菌+消毒\n";
    }
}

最后在测试一下:

package com.xq.traditonal;

import com.xq.traditonal.impl.PureMilk;
import com.xq.traditonal.impl.Terentsu;

public class TraditionalTest {
    public static void main(String[] args) {
        PureMilk pureMilk = new PureMilk();
        System.out.println(pureMilk.execute());

        Terentsu terentsu = new Terentsu();
        System.out.println(terentsu.execute());
    }
}

结果如下:

现在只有 特仑苏和纯牛奶。市面上的牛奶品种可是要非常多的,要是让你实现十几种,岂不是要多加10多个文件!

现在我们改成使用suppiler和consumer的方式实现。

这种方式要简洁很多!

我们需要将抽象类改造一下。

package com.xq.func.impl;

import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * 流程处理
 */
public class FuncProcess {
    // 牛奶工序流程
    private StringBuilder execute(Supplier<StringBuilder> supplier, Consumer<StringBuilder> consumer){
        StringBuilder f = commonHandle();
        StringBuilder stringBuilder = f.append(supplier.get());
        consumer.accept(stringBuilder);
        return assemble(stringBuilder);
    }
    // 组装处理
    private StringBuilder assemble(StringBuilder sec) {
        return sec .append(" 组装完成\n");
    }
    // 公共处理
    private StringBuilder commonHandle() {
        return new StringBuilder("通用处理一。\n") ;
    }

    // 纯牛奶
    public String pure() {
        return execute(() ->new StringBuilder("纯牛奶"), c -> c.append("杀菌+消毒+防腐剂。\n")).toString();
    }

    // 特仑苏
    public String terensu() {
        return execute(() ->new StringBuilder("特仑苏"), c -> c.append("杀菌+消毒\n")).toString();
    }
}

可以看见我们将execute的模板定义好后直接使用匿名函数的形式填充了模板所需要的方法。

Supplier充当了牛奶来源(纯牛奶or特仑苏)。
Consumer充当了特殊处理。

如果有多个特殊处理怎么办?多加几个consumer作为入参就行了。Supplier同理。

写如下测试用例:

package com.xq.func;

import com.xq.func.impl.FuncProcess;

public class FuncTest {
    public static void main(String[] args) {
        FuncProcess funcProcess = new FuncProcess();
        System.out.println(funcProcess.pure());
        System.out.println(funcProcess.terensu());
    }
}

结果:

当然,这个明显有弊端。 最大的弊端就是consumer没有返回值,所以在正常的模板模式中这些都不限制,但是在第二种需要传引用方便修改,显得有点不雅观,别扭,最好还是用于comsumer处理不需要返回的情况,比较合适。

结论

考虑的情况。

实现种类很多且都相对简单。采用suppllier,consumer方式。

想要灵活一点且种类并不多的情况。采用传统的模板模式更容易理解。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值