如何重构这段代码?

时间:2009-11-10 09:37:46

标签: java if-statement refactoring dry

请在重构此代码时提出建议。 避免代码重复,多个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;
    }

6 个答案:

答案 0 :(得分:4)

第一步是创建一个单元测试来验证此方法的行为。其次,“告诉,不要问”是良好的面向对象设计的原则,因此,如果您可以重构Field类型及其子类,实现一种允许它们在FormDataDTO上设置必要信息的方法,那将是一件好事。

答案 1 :(得分:3)

您可以从将每个案例块(if / else if块中的代码)拉入自己的方法开始。我可以看到没有太多的重复,它只是试图用一种方法做太多。

答案 2 :(得分:2)

您可以根据其外观应用策略模式;

  • 使用您在所有字段上调用的方法创建一个界面,例如FieldHandler
  • 将一个映射从ClassName初始化为FieldHandler,其中包含您需要覆盖的每个字段类型的实现(如LabelFieldHandler,DateFieldHandler等)
  • 在函数doXXX中,而不是使用instanceOf为每个字段类型执行variantions,在地图中查找相应的处理程序并将调用委托给处理程序。

伪代码:

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)

您需要在字段类型上进行调度。有多种方法可以做到这一点:

  1. 使用if语句显式测试该类。

  2. 让所有字段实现一个接口,为每个字段类型适当地实现该接口,然后调用该接口。

  3. 使用地图查找该课程的相应操作。

  4. 选项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 ...)移动到一个单独的方法,并将所需类型作为参数。