首页 » java

Java 将方法当做参数传入另一个方法

   发表于:java评论 (0)   热度:259

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・。)
喜欢这篇文章吗?欢迎分享到你的微博、QQ群,并关注我们的微博,谢谢支持。