前言
对 Java 有一定经验的小伙伴一定听说过函数式接口,网上有很多文章介绍了函数式接口的概念和和示例,但是有很多人看完就完了。处于一个 “哦我知道了” 的状态,他们会说,这个我知道了,概念也懂了,不过这个功能我在什么场合可以用到呢?好像没什么可以用到的地方啊。
实际上,如果你是一个架构师,在设计程序框架时一定可以用到的。下面我们从一个具体的应用场景加以说明。
应用场景示例
做过Android开发的小伙伴一定知道Android中的常见的弹出窗口,一般是这么用的:
AlertDialog.Builder ab = new AlertDialog.Builder(this);
ab.setMessage(message);
ab.setTitle(title);
ab.setIcon(android.R.drawable.ic_dialog_alert);
ab.setCancelable(false);
ab.setPositiveButton(R.string.ok, (dialog, which) -> {
//这里写上用户点击OK按钮后要干的事情。
);
ab.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.cancel());
AlertDialog ad = ab.create();
ad.show();
这段代码会弹出一个OK/Cancel窗口,用户点取消就啥也不干关闭窗口,点OK就执行一定的功能。基本上,这样写木有问题的。可以正常跑。
但是如果你是一个有着丰富经验的高级程序员,就一定不满足与这么写了,因为用OK/Cancel的地方可能有很多,如果每个地方都这么写,显得很繁琐,只能不断复制粘贴,然后改下message,和点OK后执行的代码内容,是不是?到处这样写程序会很杂乱。
设计改造
从设计的角度,我们希望把这个方法封装一下,做成一个通用的方法, 比如叫做showOKCancel,放到基类或者Util类里面去,以便其它地方调用
这个方法大概是这样子的:
public void showOKCancel(int title, int message)
好,思路有了,开干,开始改造这个方法,搬到基类里BaseActivity里去,
public void showOKCancel(int title, int message) {
AlertDialog.Builder ab = new AlertDialog.Builder(this);
ab.setMessage(message);
ab.setTitle(title);
ab.setIcon(android.R.drawable.ic_dialog_alert);
ab.setCancelable(false);
ab.setPositiveButton(R.string.ok, (dialog, which) ->{
// 执行OK按钮动作
);
ab.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.cancel());
AlertDialog ad = ab.create();
ad.show();
}
注意到了吗, 问题来了……这个OK按钮的代码是具体的动作,通过常规方法没办法提取出来啊,如果这部分代码不能提取出来,我们这个通用方法就搞不成,等于没做,失败了。
这个时候,我们该引入Java8 开始提供的大杀器————函数式接口了。
我们先定义个函数式接口:
@FunctionalInterface
public interface FuncRun {
void apply();
}
这个函数式接口,叫做FunRun,很简单,啥也没有,里面有一个空方法,叫做apply, 怎么用它呢?
结合我们上面的应用场景,我们把这个点OK按钮的执行代码,抽出来,作为一个参数,具体的代码放在调用showOKCancel的地方
改造后的showOKCancel 通用方法如下,加入了一个函数方法作为入参:
public void showOKCancel(int title, int message, FuncRun fr) {
AlertDialog.Builder ab = new AlertDialog.Builder(this);
ab.setMessage(message);
ab.setTitle(title);
ab.setIcon(android.R.drawable.ic_dialog_alert);
ab.setCancelable(false);
ab.setPositiveButton(R.string.ok, (dialog, which) -> fr.apply());
ab.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.cancel());
AlertDialog ad = ab.create();
ad.show();
}
看到了吗,有了这个一个参数,我们就在OK方法里直接执行了fr.apply()
至于这个fr.apply()具体是干嘛,把它放在调用的地方,我们的整理过后的通用方法showOKCancel并不关心它的内容。
比如,举例说明:在用户点击退出的地方,我们希望用户确认一下。
FuncRun fr = () -> {
System.exit(0);
};
showOKCancel(R.string.exit, R.string.exit_confirm, fr);
这样写,调用的代码十分简洁,达到了我们的设计效果。
总结
函数式接口是Java8开始引入的非常有用的功能,在设计程序框架时经常要用到。使用它可以让我们的程序更加规整,可扩展性更强。
本文示例展示了,怎样把要执行的动作作为函数入参,传入通用方法的用法,这样我们可以对Android程序做出很多有用的设计封装。
谢谢阅读。这篇文章的要点你你GET到了吗?