如何重构逻辑相同的三个方法?
How to refactor three methods with the same logic?
这是我的方法:
public List<Task> stopAndUpdateTasks(Map<Long, Future<Task>> futuresTask, List<Task> oldTasks, Map<Long, TaskStatus> oldTasksStatuses) {
futuresTask.values().forEach(f -> f.cancel(false));
final Map<Long, Task> tasksToUpdate = oldTasks.stream()
.filter(task -> futuresTask.get(task.getId()).isCancelled())
.peek(task -> task.setStatus(oldTasksStatuses.get(task.getId())))
.collect(toMap(Task::getId, task -> task));
log.info("Interrupted tasks ids:" + tasksToUpdate.keySet());
return new ArrayList<>(tasksToUpdate.values());
}
public List<PayProcess> stopAndUpdateProcesses(Map<Long, Future<PayProcess>> futures, List<PayProcess> oldProcesses, Map<Long, ProcessingStatus> processesWithStatus) {
futures.values().forEach(f -> f.cancel(false));
final Map<Long, PayProcess> processesToUpdate = oldProcesses.stream()
.filter(PayProcess -> futures.get(PayProcess.getId()).isCancelled())
.peek(payProcess -> payProcess.setProcessingStatus(processesWithStatus.get(payProcess.getId())))
.collect(toMap(PayProcess::getId, payProcess -> payProcess));
log.info("Interrupted payments ids:" + processesToUpdate.keySet());
return new ArrayList<>(processesToUpdate.values());
}
private List<Bundle> stopAndUpdateBundles(Map<Long, Future<Bundle>> futureBundles, List<Bundle> oldBundles, Map<Long, BundleStatus> oldBundleStatuses) {
futureBundles.values().forEach(f -> f.cancel(false));
final Map<Long, Bundle> bundlesToUpdate = oldBundles.stream()
.filter(task -> futureBundles.get(task.getId()).isCancelled())
.peek(bundle -> bundle.setStatus(oldBundleStatuses.get(bundle.getId())))
.collect(toMap(Bundle::getId, bundle -> bundle));
log.info("Interrupted bundles ids:" + bundlesToUpdate.keySet());
return new ArrayList<>(bundlesToUpdate.values());
}
你能建议我一些非常酷的方法来重构这些方法吗?我无法想象该怎么做,但我必须这样做。我尝试为实体编写泛型和接口,但它们不适用于 Future
这是我的解决方法:
如您所见 - 实体实现了所需的接口,但它不起作用
您可以通过这种方式完成(而不是使用通配符泛型)。注意 - 这假设 Task、Bundle 和 PayProcess 没有现有的公共超类。
创建抽象超类:
public abstract class CommonSuperClass<T>{
private Long id;
private T status;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public T getStatus() {
return status;
}
public void setStatus(T status) {
this.status = status;
}
}
现在让 Task 、PayProcess 和 Bundle 扩展它:
public class Task extends CommonSuperClass<TaskStatus>{
...
}
public class PayProcess extends CommonSuperClass<ProcessingStatus>{
...
}
现在像这样定义你的方法:
public static <T extends CommonSuperClass<U>, U> List<T> stopAndUpdate(Map<Long, Future<T>> futures,
List<T> oldList,
Map<Long, U> oldStatuses) {
futures.values().forEach(f -> f.cancel(false));
final Map<Long, T> updates = oldList.stream()
.filter(t -> futures.get(t.getId()).isCancelled())
.peek(task -> task.setStatus(oldStatuses.get(task.getId())))
.collect(toMap(t -> t.getId(), Function.identity()));
//log.info("Interrupted tasks ids:" + tasksToUpdate.keySet());
return new ArrayList(updates.values());
}
有了这个你可以像这样使用:
Map<Long, Future<Task>> futuresTask = new HashMap<>();
List<Task> oldTasks = new ArrayList<>();
Map<Long, TaskStatus> oldTasksStatuses = new HashMap<>();
stopAndUpdate(futuresTask, oldTasks, oldTasksStatuses);
Map<Long, Future<PayProcess>> futures = new HashMap<>();
List<PayProcess> oldProcesses = new ArrayList<>();
Map<Long, ProcessingStatus> processesWithStatus = new HashMap<>();
stopAndUpdate(futures, oldProcesses, processesWithStatus);
只有当你已经有了这个关系时你才能这样做,或者你可以通过某种方式改变你的代码来做到这一点
private List<Item> stopAndUpdate(Map<Long, Future<Item>> futureItems, List<Item> oldItems, Map<Long, Status> oldStatuses) {
futureItems.values().forEach(f -> f.cancel(false));
final Map<Long, Item> itemsToUpdate = oldItems.stream()
.filter(task -> futureItems.get(task.getId()).isCancelled())
.peek(item -> item.setStatus(oldStatuses.get(item.getId())))
.collect(toMap(Item::getId, item -> item));
log.info("Interrupted bundles ids:" + itemsToUpdate.keySet());
return new ArrayList<>(itemsToUpdate.values());
}
需要关系
interface Item {
Long getId();
void setStatus(Status status);
}
interface Status {
}
class Task implements Item {
@Override
public Long getId() {
return null;
}
@Override
public void setStatus(Status status) {
}
}
class PayProcess implements Item {
@Override
public Long getId() {
return null;
}
@Override
public void setStatus(Status status) {
}
public void setProcessingStatus(Status status) {
}
}
class Bundle implements Item {
@Override
public Long getId() {
return null;
}
@Override
public void setStatus(Status status) {
}
}
class TaskStatus implements Status{}
class ProcessingStatus implements Status{}
class BundleStatus implements Status{}
这是我的方法:
public List<Task> stopAndUpdateTasks(Map<Long, Future<Task>> futuresTask, List<Task> oldTasks, Map<Long, TaskStatus> oldTasksStatuses) {
futuresTask.values().forEach(f -> f.cancel(false));
final Map<Long, Task> tasksToUpdate = oldTasks.stream()
.filter(task -> futuresTask.get(task.getId()).isCancelled())
.peek(task -> task.setStatus(oldTasksStatuses.get(task.getId())))
.collect(toMap(Task::getId, task -> task));
log.info("Interrupted tasks ids:" + tasksToUpdate.keySet());
return new ArrayList<>(tasksToUpdate.values());
}
public List<PayProcess> stopAndUpdateProcesses(Map<Long, Future<PayProcess>> futures, List<PayProcess> oldProcesses, Map<Long, ProcessingStatus> processesWithStatus) {
futures.values().forEach(f -> f.cancel(false));
final Map<Long, PayProcess> processesToUpdate = oldProcesses.stream()
.filter(PayProcess -> futures.get(PayProcess.getId()).isCancelled())
.peek(payProcess -> payProcess.setProcessingStatus(processesWithStatus.get(payProcess.getId())))
.collect(toMap(PayProcess::getId, payProcess -> payProcess));
log.info("Interrupted payments ids:" + processesToUpdate.keySet());
return new ArrayList<>(processesToUpdate.values());
}
private List<Bundle> stopAndUpdateBundles(Map<Long, Future<Bundle>> futureBundles, List<Bundle> oldBundles, Map<Long, BundleStatus> oldBundleStatuses) {
futureBundles.values().forEach(f -> f.cancel(false));
final Map<Long, Bundle> bundlesToUpdate = oldBundles.stream()
.filter(task -> futureBundles.get(task.getId()).isCancelled())
.peek(bundle -> bundle.setStatus(oldBundleStatuses.get(bundle.getId())))
.collect(toMap(Bundle::getId, bundle -> bundle));
log.info("Interrupted bundles ids:" + bundlesToUpdate.keySet());
return new ArrayList<>(bundlesToUpdate.values());
}
你能建议我一些非常酷的方法来重构这些方法吗?我无法想象该怎么做,但我必须这样做。我尝试为实体编写泛型和接口,但它们不适用于 Future
这是我的解决方法:
如您所见 - 实体实现了所需的接口,但它不起作用
您可以通过这种方式完成(而不是使用通配符泛型)。注意 - 这假设 Task、Bundle 和 PayProcess 没有现有的公共超类。
创建抽象超类:
public abstract class CommonSuperClass<T>{
private Long id;
private T status;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public T getStatus() {
return status;
}
public void setStatus(T status) {
this.status = status;
}
}
现在让 Task 、PayProcess 和 Bundle 扩展它:
public class Task extends CommonSuperClass<TaskStatus>{
...
}
public class PayProcess extends CommonSuperClass<ProcessingStatus>{
...
}
现在像这样定义你的方法:
public static <T extends CommonSuperClass<U>, U> List<T> stopAndUpdate(Map<Long, Future<T>> futures,
List<T> oldList,
Map<Long, U> oldStatuses) {
futures.values().forEach(f -> f.cancel(false));
final Map<Long, T> updates = oldList.stream()
.filter(t -> futures.get(t.getId()).isCancelled())
.peek(task -> task.setStatus(oldStatuses.get(task.getId())))
.collect(toMap(t -> t.getId(), Function.identity()));
//log.info("Interrupted tasks ids:" + tasksToUpdate.keySet());
return new ArrayList(updates.values());
}
有了这个你可以像这样使用:
Map<Long, Future<Task>> futuresTask = new HashMap<>();
List<Task> oldTasks = new ArrayList<>();
Map<Long, TaskStatus> oldTasksStatuses = new HashMap<>();
stopAndUpdate(futuresTask, oldTasks, oldTasksStatuses);
Map<Long, Future<PayProcess>> futures = new HashMap<>();
List<PayProcess> oldProcesses = new ArrayList<>();
Map<Long, ProcessingStatus> processesWithStatus = new HashMap<>();
stopAndUpdate(futures, oldProcesses, processesWithStatus);
只有当你已经有了这个关系时你才能这样做,或者你可以通过某种方式改变你的代码来做到这一点
private List<Item> stopAndUpdate(Map<Long, Future<Item>> futureItems, List<Item> oldItems, Map<Long, Status> oldStatuses) {
futureItems.values().forEach(f -> f.cancel(false));
final Map<Long, Item> itemsToUpdate = oldItems.stream()
.filter(task -> futureItems.get(task.getId()).isCancelled())
.peek(item -> item.setStatus(oldStatuses.get(item.getId())))
.collect(toMap(Item::getId, item -> item));
log.info("Interrupted bundles ids:" + itemsToUpdate.keySet());
return new ArrayList<>(itemsToUpdate.values());
}
需要关系
interface Item {
Long getId();
void setStatus(Status status);
}
interface Status {
}
class Task implements Item {
@Override
public Long getId() {
return null;
}
@Override
public void setStatus(Status status) {
}
}
class PayProcess implements Item {
@Override
public Long getId() {
return null;
}
@Override
public void setStatus(Status status) {
}
public void setProcessingStatus(Status status) {
}
}
class Bundle implements Item {
@Override
public Long getId() {
return null;
}
@Override
public void setStatus(Status status) {
}
}
class TaskStatus implements Status{}
class ProcessingStatus implements Status{}
class BundleStatus implements Status{}