重构:AbstractList适配器与Java 7中的每次转换?

时间:2018-03-12 14:06:37

标签: java coding-style refactoring

什么时候应该使用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知道如何创建单个ErrorMessage ObjectError个实例:

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方法可以替换为List适配器:

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;
}

这种变体增加了许多代码和一些间接性,但似乎增加了模块性,可重用性和可测试性(?)。

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

1 个答案:

答案 0 :(得分:0)

使用toString()的代码更复杂,更难以理解。 既然你没有任何具体的理由来重构这个(过早的优化?),我会保持原样。