我使用两个api调用来获取有关vehicleUtils的数据,具体取决于contentFilter。我有两个非常相似的代码(司机和车辆)。我试图做的是将代码提取到一个单一的方法,并应用像他们在这里建议的战略模式Refactoring methods,但我无法弄清楚如何实现它。我使用的是一种好的方法还是有更好的方法?
if (contentFilter.equalsIgnoreCase(Contentfilters.VEHICLES.toString())) {
VuScores vuScores = new VuScores();
List<VehicleVuScores> vehicleVuScoresList = new ArrayList<>();
List<VehicleUtilization> vehicleUtilizations = RestClient.getVehicles(request).join().getVehicleUtilizations();
if (Objects.nonNull(vehicleUtilizations)) {
vehicleUtilizations.forEach(vehicleUtilization -> {
vuScores.getVehicleVuScores().forEach(vehicleVuScore -> {
vehicleVuScore.getScores().setTotal(vehicleUtilization.getFuelEfficiencyIndicators().getTotal().getValue());
vehicleVuScore.getScores().setBraking(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(3).getIndicators().get(0).getValue());
vehicleVuScore.getScores().setCoasting(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(3).getIndicators().get(1).getValue());
vehicleVuScore.getScores().setIdling(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(0).getIndicators().get(0).getValue());
vehicleVuScore.getScores().setAnticipation(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(3).getValue());
vehicleVuScore.getScores().setEngineAndGearUtilization(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(1).getValue());
vehicleVuScore.getScores().setStandstill(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(0).getValue());
vehicleVuScore.getScores().setWithinEconomy(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(1).getIndicators().get(7).getValue());
vehicleVuScore.setAvgFuelConsumptionPer100Km(vehicleUtilization.getMeasures().getTotal().getAverageConsumption().getValue());
vehicleVuScore.setAvgSpeedDrivingKmh(vehicleUtilization.getMeasures().getTotal().getAverageSpeed().getValue());
vehicleVuScore.setEngineLoad(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(1).getIndicators().get(1).getValue());
vehicleVuScore.setTotalDistanceInKm(vehicleUtilization.getMeasures().getDriving().getDistance().getValue());
vehicleVuScore.setTotalTime(Math.toIntExact(vehicleUtilization.getMeasures().getTotal().getTime().getValue()));
vehicleVuScoresList.add(vehicleVuScore);
});
});
vuScores.setVehicleVuScores(vehicleVuScoresList);
}
return CompletableFuture.completedFuture(vuScores);
} else if (contentFilter.equalsIgnoreCase(Contentfilters.DRIVERS.toString())) {
VuScores vuScores = new VuScores();
List<DriverVuScores> driverVuScoresList = new ArrayList<>();
List<VehicleUtilization> vehicleUtilizations = RestClient.getDrivers(request).join().getVehicleUtilizations();
if (Objects.nonNull(vehicleUtilizations)) {
vehicleUtilizations.forEach(vehicleUtilization -> {
vuScores.getDriverVuScores().forEach(driverVuScores -> {
driverVuScores.getScores().setTotal(vehicleUtilization.getFuelEfficiencyIndicators().getTotal().getValue());
driverVuScores.getScores().setBraking(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(3).getIndicators().get(0).getValue());
driverVuScores.getScores().setCoasting(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(3).getIndicators().get(1).getValue());
driverVuScores.getScores().setIdling(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(0).getIndicators().get(0).getValue());
driverVuScores.getScores().setAnticipation(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(3).getValue());
driverVuScores.getScores().setEngineAndGearUtilization(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(1).getValue());
driverVuScores.getScores().setStandstill(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(0).getValue());
driverVuScores.getScores().setWithinEconomy(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(1).getIndicators().get(7).getValue());
driverVuScores.setAvgFuelConsumptionPer100Km(vehicleUtilization.getMeasures().getTotal().getAverageConsumption().getValue());
driverVuScores.setAvgSpeedDrivingKmh(vehicleUtilization.getMeasures().getTotal().getAverageSpeed().getValue());
driverVuScores.setEngineLoad(vehicleUtilization.getFuelEfficiencyIndicators().getGroupIndicators().get(1).getIndicators().get(1).getValue());
driverVuScores.setTotalDistanceInKm(vehicleUtilization.getMeasures().getDriving().getDistance().getValue());
driverVuScores.setTotalTime(Math.toIntExact(vehicleUtilization.getMeasures().getTotal().getTime().getValue()));
driverVuScoresList.add(driverVuScores);
});
});
vuScores.setDriverVuScores(driverVuScoresList);
}
return CompletableFuture.completedFuture(vuScores);
}
尝试考虑一个包含公共代码的公共(抽象)基类。实际的类包含不同的代码。
然后,您无需使用instanceof或Contentfilters或您使用的任何类型的decission功能。您可以调用常用方法,因为您的函数应该使用(抽象)基类。这确实消除了代码重复。
使用接口,在两个类中实现它,并在两个地方使用该接口来获取或设置值。由于所有方法名称都相同,因此接口应包含所有必需的getter和setter。这样您就不必使用不同的类。
所以,除了之外,一切都是一样的
主要挑战是共享调用setter的代码。我们需要一种方法来引用目标对象,而无需知道它是VehicleVuScores还是DriverVuScores。我们可以声明为:
Object vuScores;
但由于Object
没有声明setter,我们在尝试调用setter时会遇到编译错误。为了解决这个问题,我们可以将这些getter和setter的声明移动到一个公共基类型:
abstract class VuScoresBase {
// fields, getters and setters
}
class DriverVuScores extends VuScoresBase {}
class VehicleVuScores extends VuScoresBase {}
所以我们可以写:
public void convert(VehicleUtilization vehicleUtilization, VuScoresBase result) {
// invoke the setters here
}
并在两种情况下使用此方法。
使用泛型,我们也可以重用迭代代码:
<V extends VuScoresBase> public void convertList(List<VehicleUtilization> vehicleUtilizations, List<V> resultList, Supplier<V> constructor) {
// iterate
V vuScore = constructor.apply();
convert(vehicleUtilization, vuScore);
resultList.add(vuScore);
}
所以我们可以调用它
convertList(vehicleUtilizations, driverVuScores, DriverVuScore::new);
但我可能会避免这种情况,因为泛型使代码难以理解。
但是,由于DriverVuScores和VehicleVuScores非常相似,我怀疑我们是否真的需要它们作为单独的类型。如果我们可以在任何地方使用VuScoresBase,这将极大地简化转换逻辑:
VuScoresBase convert(VehicleUtilization vehicleUtilization) {
VuScoresBase vuScores = new VuScoreBase();
// invoke setters
return vuScores;
}
和
List<VuScoresBase> convertList(List<VehicleUtilization> vehicleUtilizations) {
// iterate
result.add(convert(vehicleUtilization));
}