请在重构此代码时提出建议。 避免代码重复,多个Ifs
public FormDataDTO getDataForFieldFormCHrzntalField(Field field) {
FormDataDTO formDataDTO = new FormDataDTO();
CHrzntalField cHrzntalField = (CHrzntalField) field;
for (int j = 0; j < cHrzntalField.getFieldCount(); j++) {
Field sField = cHrzntalField.getField(j);
if (sField instanceof LabelField) {
LabelField labelField = sField;
String fieldName = labelField.getText();
System.out.println("The Label field name is " + fieldName);
formDataDTO.setFieldName(fieldName);
} else if (sField instanceof CTextFieldBorder) {
CTextFieldBorder cTextFieldBorder = (CTextFieldBorder) sField;
Field ssField = cTextFieldBorder.getField(0);
if (ssField instanceof TextField) {
TextField textField = ssField;
System.out.println("Inside TextField---- "
+ textField.getText());
formDataDTO.setFieldType("TextField");
formDataDTO.setSelectedValue(textField.getText());
} else if (ssField instanceof DateField) {
DateField dateField = ssField;
String dateString = dateField.toString();
System.out.println("dateString " + dateString);
formDataDTO.setFieldType("Date");
formDataDTO.setSelectedValue(dateString);
}
} else if (sField instanceof CChoiceField) {
CChoiceField cChoiceField = (CChoiceField) sField;
int i = cChoiceField.getSelectedIndex();
String selectedValue = cChoiceField.getChoice(i);
System.out.println("Choice " + selectedValue);
formDataDTO.setFieldType("Combo");
formDataDTO.setSelectedValue(selectedValue);
} else if (sField instanceof CheckboxField) {
CheckboxField checkboxField = (CheckboxField) sField;
boolean checkStatus = checkboxField.getChecked();
System.out.println("Check box field " + checkStatus);
formDataDTO.setFieldType("Checkbox");
String status = new Boolean(checkStatus).toString();
formDataDTO.setSelectedValue(status);
}
}
return formDataDTO;
}
答案 0 :(得分:4)
第一步是创建一个单元测试来验证此方法的行为。其次,“告诉,不要问”是良好的面向对象设计的原则,因此,如果您可以重构Field类型及其子类,实现一种允许它们在FormDataDTO上设置必要信息的方法,那将是一件好事。
答案 1 :(得分:3)
您可以从将每个案例块(if / else if块中的代码)拉入自己的方法开始。我可以看到没有太多的重复,它只是试图用一种方法做太多。
答案 2 :(得分:2)
您可以根据其外观应用策略模式;
FieldHandler
伪代码:
field = getField(j);
handler = handlerMap.get(field.className);
if (null == handler) {
// error unknown field type
} else {
handler.setFormData(field, formDataDTO);
}
答案 3 :(得分:1)
在Field
中添加一个新的抽象方法public class Field {
public abstract void updateFormData(FormDataDTO formDataDTO);
}
然后,在Field的每个子类中实现它。
最后,您的代码变为:
public FormDataDTO getDataForFieldFormCHrzntalField(Field field) {
FormDataDTO formDataDTO = new FormDataDTO();
CHrzntalField cHrzntalField = (CHrzntalField) field;
for (int j = 0; j < cHrzntalField.getFieldCount(); j++) {
Field sField = cHrzntalField.getField(j);
sField.updateFormData(formDataDTO);
}
return formDataDTO;
}
答案 4 :(得分:1)
您需要在字段类型上进行调度。有多种方法可以做到这一点:
使用if语句显式测试该类。
让所有字段实现一个接口,为每个字段类型适当地实现该接口,然后调用该接口。
使用地图查找该课程的相应操作。
选项1是你现在正在做的事情; 2是Stroboskop提到的; 3通过rsp称为策略模式。你可以看到,1有点乱。 2将上述方法的工作与田地相结合,而3则没有。选择中的哪一个(2或3)取决于您的具体情况。 (2)的一个优点是你不要忘记为每个新字段编写代码(因为如果忘记了,你会得到编译器错误)。 (3)的一个优点是,如果你想多次做这种事情,那些领域就会变得杂乱无章。此外,(2)要求您可以访问字段代码。
值得注意的是,如果你使用的是Scala而不是Java,那么(2)的一些问题可以通过特征来避免(并且它对于(1)模式匹配也有更好的语法)。
个人我希望(2)如果可能的话 - 或许可以通过委托来实现它。 (3)优于(1)的唯一真正优点是代码更整洁 - 并且有一点额外的类型安全性。答案 5 :(得分:0)
您应该使用方法重载来避免实例调用。应将每个if (sField instanceof ...)
移动到一个单独的方法,并将所需类型作为参数。