重构:Java 7 中的抽象列表适配器与每个转换?



什么时候使用使用AbstractList的适配器模式应该优于通过for-each从另一个列表构建结果列表?

给定以下 Java bean(为了可读性而跳过 getter/setter):

class ObjectError {
private String code;
}
class FieldError extends ObjectError {
private String field;
}
class ErrorMessage {
private String path;
private String messageKey;
}

以及Validator类的以下方法:

public AllErrors validate(List<ObjectError> errors) {
AllErrors result= new AllErrors();
result.setErrors(convertErrors(errors));
return result;
}
List<ErrorMessage> convertErrors(List<ObjectError> errors) {
List<ErrorMessage> result = new ArrayList<>(errors.size());
for (ObjectError error : errors) {
ErrorMessage message = new ErrorMessage();
if (error instanceof FieldError) {
message.setMessageKey(((FieldError) error)).getPath();
}
message.setPath(error.getCode());
result.add(message);
}
return result;
}

我想重构convertErrors.

首先,我们可以将 for 循环的内容提取到createErrorMessage方法中,这样convertErrors列表迭代,createErrorMessage知道如何从ObjectError实例创建单个ErrorMessage

List<ErrorMessage> convertErrors(List<ObjectError> errors) {
List<ErrorMessage> result = new ArrayList<>(errors.size());
for (ObjectError error : errors) {
result.add(createErrorMessage(error));
}
return result;
}
ErrorMessage createErrorMessage(ObjectError error) {
ErrorMessage message = new ErrorMessage();
if (error instanceof FieldError) {
message.setMessageKey(((FieldError) error)).getPath();
}
message.setPath(error.getCode());
return message;
}

现在有两个选项:

保持现状

当前代码可以从上到下读取,但Validator类的组件不太可重用。

使用AbstractList适配器

convertErrors方法可以替换为列表适配器:

private static class ObjectErrorAdapter extends AbstractList<ErrorMessage> {
private List<ObjectError> objectErrors;
private ObjectErrorAdapter(List<ObjectError> objectErrors) {
this.objectErrors = objectErrors;
}
@Override public ErrorMessage get(int idx) {
return createErrorMessage(objectErrors.get(idx));
}
@Override public int size() {
return objectErrors.size();
}
ErrorMessage createErrorMessage(ObjectError error) {
ErrorMessage message = new ErrorMessage();
if (error instanceof FieldError) {
message.setMessageKey(((FieldError) error)).getPath();
}
message.setPath(error.getCode());
return message;
}
// Also hashCode() and equals() might be required for this class   
}
public AllErrors validate(List<ObjectError> errors) {
AllErrors result= new AllErrors();
result.setErrors(new ObjectErrorAdapter(errors));
return result;
}

这个变体增加了很多代码和一些间接,但似乎增加了模块化、可重用性,从而增加了可测试性(?)。

哪种变体更可取,为什么?

使用AbstractList的代码更复杂且更难理解。 由于您没有任何具体的理由来重构它(过早优化?),我会保持原样。

最新更新