背景
说到Java8新特性,大家可能都耳濡目染了,代码中经常使用遍历stream流用到不同的api了,但是大家有没有想过自己也自定义个函数式接口呢,目前Java8自带的四个函数式接口,比如Function、Supplier等
stream流中也使用到了,但是这四个函数式接口不仅仅只是为了遍历stream流而产生的,可以在别的地方也可以单独使用这个四个函数式接口,甚至四个不够可以自定义一个都可以
自定义函数式接口
@FunctionalInterface
public interface StatusProcessFunction {
/**
* 整车大版本策略-有效/无效处理逻辑
*
* @param status 有效:1 无效:0
* @return void
**/
void statusMessageProcess(String status);
}
/**
* 如果参数为有效:1 ---> 该目标大版本下所有原版本策略都是有效的,可以继续
* 反之无效:0 ----> 该目标大版本下所有原版本策略都是无效的,需要将策略都设置失效状态 2、策略关联的任务都设置为失效状态
*
* @param status 有效:1 无效:0
* @return com.adups.iov.open.api.vsp.service.StatusProcessFunction
**/
private StatusProcessFunction isValid(String status, String versionCode) {
return (errorMessage) -> {
if (Objects.equals(status, ZERO)) {
// 通过目标大版本号且是有效状态的获取所有的关联任务id
List<TaskStrategyInfoDO> taskStrategyInfoDOS = bigVersionInfoMapper.queryTaskIdsByVersionCode(versionCode);
boolean anyMatchTask = taskStrategyInfoDOS.stream().anyMatch(s -> !ObjectUtils.isEmpty(s.getTaskId()));
if (anyMatchTask) {
// 批量修改任务的状态置为已失效
strategyInfoMapper.updateTaskStatusByVersionCode(taskStrategyInfoDOS);
}
boolean anyMatchStrategy = taskStrategyInfoDOS.stream().anyMatch(s -> !ObjectUtils.isEmpty(s.getStrategyId()));
if (anyMatchStrategy) {
// 批量修改策略的状态置为已失效
strategyInfoMapper.updateStrategyStatusByVersionCode(taskStrategyInfoDOS);
}
log.info("整车大版本策略-目标大版本已置为失效状态,目标版本下的策略和任务均置为已失效:status -->{}," +
"versionCode-->{},业务异常信息:{}", status, versionCode, errorMessage);
}
};
}
/**
* 保存整车大版本策略信息
*
* @param {@link versionStrategyInfoDTO}<{@link VehicleVersionStrategyInfoDTO}> 整车大版本策略信息入参模型
* @return BigVersionInfoDO 返回整车大版本策略信息(包含主键id)
*/
private BigVersionInfoDO saveBigVersionInfo(VehicleVersionStrategyInfoDTO versionStrategyInfoDTO) {
// 构建BigVersionInfoDO对象-填充入库属性
BigVersionInfoDO bigVersionConvertDO = StrategyInfoConvert.INSTANCE.dtoStrategyBigVersionConvertDO(versionStrategyInfoDTO.getVehicleBigVersion());
bigVersionConvertDO.setModelId(vehicleModelMapper.getModelIdByElectricalPlatform(bigVersionConvertDO.getElectricalPlatform()));
// 新增整车大版本信息如果重复就更新否则就插入
isValid(bigVersionConvertDO.getStatus(), bigVersionConvertDO.getVersionCode()).statusMessageProcess(DataSyncConstant.PO_STRATEGY_RESPONSE_LOG);
bigVersionInfoMapper.saveBigVersionInfo(bigVersionConvertDO);
return bigVersionConvertDO;
}
函数式接口替代策略模式-Supplier
说到策略模式,大家肯定都用到过我之前有篇已经说过策略模式+工厂方法
大家其实都知道有时候设计模式并不是为了简化代码的,更多的是为了扩展性的,但是有时候并不是适用所有场景,当然通过不同类型发生不同的行为,前提这些行为的步骤都是一样的,只是有些行为的内容不一样,这个时候你当然可以使用策略模式+工厂方法,但是也可以使用函数式接口
需求
现在有四个控制层,但是业务层都可以封装一个,只是参数不同而已,当然你也可以都拆开,但是这些肯定idea会提示很多重复代码嘛,对于这种就可以传入一个函数式接口作为形参
@Slf4j
@RestController
public class PackageInfoSyncController {
@Autowired
private VspAsyncServiceCommonHandle serviceCommonHandle;
/**
* 软件包信息同步
*
* @param requestDTO po入参
* @return POResponseVO
*/
@PostMapping("/ota/package/info")
public POResponseVO packageInfoParse(@RequestBody PORequestDTO requestDTO) {
return serviceCommonHandle.asyncServiceCommonHandle(requestDTO, () -> MapUtil.builder()
.put(DataSyncConstant.TYPE, DataSyncEnum.PACKAGE_INFO.getType())
.put(DataSyncConstant.RESPONSE, DataSyncConstant.PO_PACKAGE_RESPONSE_EXISTED_LOG)
.put(DataSyncConstant.RESULT, DataSyncConstant.PO_PACKAGE_RESPONSE_LOG)
.build());
}
}
/**
* VSP平台策略信息同步信息
*
* @param requestDTO 同步数据
* @param mapSupplier mapSupplier
* @return {@link POResponseVO}
*/
public POResponseVO asyncServiceCommonHandle(PORequestDTO requestDTO, Supplier<Map<Object, Object>> mapSupplier) {
...中间的业务代码都省略
String hashCount = strategyInfoMapper.querySyncStrategyInfo(hash, (Integer)mapSupplier.get().get(DataSyncConstant.TYPE));
return new POResponseVO();
}
函数式接口替代策略模式-Function
在Java 8中,您可以使用java.util.function.Function接口来传递行为(功能)作为参数。下面是一个简单的示例,演示如何将相同的代码抽取出来,并通过Function函数式接口传递不同的行为:
import java.util.function.Function;
public class FunctionExample {
public static void main(String[] args) {
// 示例1:将字符串转换为大写
String result1 = processString("Hello, World!", str -> str.toUpperCase());
System.out.println("Result 1: " + result1);
// 示例2:将字符串转换为小写
String result2 = processString("Hello, World!", str -> str.toLowerCase());
System.out.println("Result 2: " + result2);
// 示例3:将字符串长度加倍
Integer result3 = processInteger(5, num -> num * 2);
System.out.println("Result 3: " + result3);
}
// 通用方法,接受一个字符串和一个 Function 接口实例
private static String processString(String input, Function<String, String> function) {
return function.apply(input);
}
// 通用方法,接受一个整数和一个 Function 接口实例
private static Integer processInteger(Integer input, Function<Integer, Integer> function) {
return function.apply(input);
}
}
在上述示例中,processString方法和processInteger方法接受一个泛型参数(字符串或整数),以及一个Function接口的实例作为参数。通过传递不同的Function实例,您可以实现对相同代码的不同行为。在示例中,分别演示了将字符串转换为大写、小写以及将整数加倍的三种不同行为。