Java 将方法当做参数传入另一个方法
1、背景
最近工作中遇到一个情况,需要写6个很相似的查询功能,着6个查询的唯一的区别就是返回实体的字段不相同。
例如:我的待办需求,待办查询方式是一样的,但是待办分为好多种类型,每种类型的列表展示信息又是不一致的。
考虑到代码复用,打算写一个公共的查询方法,返回一个泛型,并且将最后组装返回实体的逻辑由上层的方法进行传入,由调用端指定公共方法内组装实体的逻辑以及返回的类型。
2、实现(函数式编程)-如果直接想要看简单示例,直接拉到第3点,有各种简单示例
2.1、先定义了一个带有泛型参数的函数式接口 TodoFunction
函数式接口需要加上@FunctionalInterface注解,接口中定义一个execute方法,传入一个查询结果queryList和一个返回结果result,代码如下:
@FunctionalInterface
public interface TodoListFunction<T> {
void execute(List<Map<String, String>> queryList, List<T> result);
}
2.2、写两个具体的业务方法实现上述execute方法(不需要继承)
实现不同类型待办的实体赋值逻辑,代码如下:
/**
* 代办A
*/
public class ATodoService {
/**
* 代办A.
* @param queryList
* @param result
*/
public static void execute(List<Map<String, String>> queryList, List<ATodoDto> result) {
// 此处可以执行自己的一些特有逻辑
// ...
for (var queryItem : queryList) {
var item = new ATodoDto();
item.setA(queryItem.get("A"));
item.setB(queryItem.get("B"));
result.add(item);
}
}
}
/**
* 代办B
*/
public class BTodoService {
/**
* 代办B.
* @param queryList
* @param result
*/
public static void execute(List<Map<String, String>> queryList, List<BTodoDto> result) {
// 此处可以执行自己的一些特有逻辑
// ...
for (var queryItem : queryList) {
var item = new BTodoDto();
item.setC(queryItem.get("C"));
item.setD(queryItem.get("D"));
result.add(item);
}
}
}
2.3、写一个处理公共逻辑的方法,并且将2.1定义的TodoFunction作为参数传入
/**
* 代办查询
* @param request
* @return
*/
private <T> List<T> getTodoList(List<Map<String, String>> queryList, TodoListFunction todoMethod) {
// 处理一些公共逻辑
// TODO ......
List<T> result = new ArrayList<>();
// 执行具体方法(会根据实际上端根据传入的方法进行执行)
todoMethod.execute(queryList, result);
return result;
}
2.4、上端调用
/**
* 获取A代办
* @param request
* @return
*/
public List<ATodoDto> getATodoList(List<Map<String, String>> queryList) {
return getTodoList(queryList, ATodoService::execute);
}
/**
* 获取B代办
* @param request
* @return
*/
public List<BTodoDto> getBTodoList(List<Map<String, String>> queryList) {
return getTodoList(queryList, BTodoService::execute);
}
总结:这里A待办和B待办共同调用getTodoList方法,但是传入的execute方法不同,最终在getTodoList方法中执行不同的execute方法,从而满足我们的需求
3、Java中各种函数式编程实现示例
3.1、不带参数方式(Runnable 为自带类)
public class Main {
public static void main(String[] args) {
executeMethod(() -> {
System.out.println("Hello, World!");
});
}
public static void executeMethod(Runnable method) {
// 在被传入的方法内执行传入的方法
method.run();
}
}
在上述示例中,定义了一个 executeMethod() 方法,它接收一个 Runnable 参数,即一个函数式接口。然后,在 main() 方法中调用 executeMethod() 方法,并通过 Lambda 表达式传入一个方法的实现。在被传入的方法 executeMethod() 中,通过调用 Runnable 接口的 run() 方法来执行传入的方法。
3.2、带一个参数方式
import java.util.function.Consumer;
public class Main {
public static void main(String[] args) {
executeMethod("Hello, World!", message -> {
System.out.println("Received message: " + message);
});
}
public static void executeMethod(String message, Consumer<String> method) {
// 在被传入的方法内执行传入的方法,并传递参数
method.accept(message);
}
}
在上述示例中,定义了一个 executeMethod() 方法,它接收一个字符串参数 message 和一个 Consumer<String> 参数 method,即接受一个字符串参数并返回 void 的函数式接口。然后,在 main() 方法中调用 executeMethod() 方法,并通过 Lambda 表达式传入一个带参数的方法实现。在被传入的方法 executeMethod() 中,通过调用 Consumer 接口的 accept() 方法来执行传入的方法,并传递参数。
3.3、带多个参数方式
@FunctionalInterface
interface MyFunction {
void execute(int a, int b, String message);
}
public class Main {
public static void main(String[] args) {
executeMethod(10, 20, "Hello", (a, b, message) -> {
System.out.println("Received parameters: a = " + a + ", b = " + b + ", message = " + message);
});
}
public static void executeMethod(int a, int b, String message, MyFunction method) {
// 在被传入的方法内执行传入的方法,并传递参数
method.execute(a, b, message);
}
}
3.4、泛型并且带多个参数
@FunctionalInterface
interface MyFunction<T> {
void execute(T value, int a, int b);
}
public class Main {
public static void main(String[] args) {
executeMethod("Hello", 10, 20, (value, a, b) -> {
System.out.println("Received parameters: value = " + value + ", a = " + a + ", b = " + b);
});
}
public static <T> void executeMethod(T value, int a, int b, MyFunction<T> method) {
// 在被传入的方法内执行传入的方法,并传递参数
method.execute(value, a, b);
}
}
3.5、泛型并且带多个参数(非Lambda方式),毕竟实际业务中逻辑比较复杂, 不可能在一个Lambda里面写上很多业务逻辑
@FunctionalInterface
interface MyFunction<T> {
void execute(T value, int a, int b);
}
public class Main {
public static void main(String[] args) {
executeMethod("Hello", 10, 20, Main::processParameters);
}
public static <T> void executeMethod(T value, int a, int b, MyFunction<T> method) {
// 在被传入的方法内执行传入的方法,并传递参数
method.execute(value, a, b);
}
public static <T> void processParameters(T value, int a, int b) {
System.out.println("Received parameters: value = " + value + ", a = " + a + ", b = " + b);
}
}
(。・v・。)