Разложение сложного метода с помощью переключателя - PullRequest
1 голос
/ 08 марта 2019

В моем приложении есть логика, которая зависит от типа параметра, и теперь она работает следующим образом:

   switch (parameter.getType()) {
                case DOUBLE:
                    countOfParameters = parameter.getDoubleValueCount();
                    if (countOfParameters == 1) {
                        propertiesBuilder.addProperty(parameter.getName(), parameter.getDoubleValue(0));
                    } else if (countOfParameters > 1) {
                        Double[] doubleValues = new Double[countOfParameters];
                        for (int kj = 0; kj < countOfParameters; kj++) {
                            doubleValues[kj] = parameter.getDoubleValue(kj);
                        }
                        propertiesBuilder.addProperty(parameter.getName(), doubleValues);
                    }
                    break;
                case BOOLEAN:
                    countOfParameters = parameter.getBoolValueCount();
                    if (countOfParameters == 1) {
                        propertiesBuilder.addProperty(parameter.getName(), parameter.getBoolValue(0));
                    } else if (countOfParameters > 1) {
                        Boolean[] booleanValues = new Boolean[countOfParameters];
                        for (int kj = 0; kj < countOfParameters; kj++) {
                            booleanValues[kj] = parameter.getBoolValue(kj);
                        }
                        propertiesBuilder.addProperty(parameter.getName(), booleanValues);
                    }
                    break;
                case STRING:
                    countOfParameters = parameter.getStringValueCount();
                    if (countOfParameters == 1) {
                        propertiesBuilder.addProperty(parameter.getName(), parameter.getStringValue(0));
                    } else if (countOfParameters > 1) {
                        String[] stringValues = new String[countOfParameters];
                        for (int kj = 0; kj < countOfParameters; kj++) {
                            stringValues[kj] = parameter.getStringValue(kj);
                        }
                        propertiesBuilder.addProperty(parameter.getName(), stringValues);
                        break;
                    }
                case INTEGER:
                    countOfParameters = parameter.getIntValueCount();
                    if (countOfParameters == 1) {
                        propertiesBuilder.addProperty(parameter.getName(), parameter.getIntValue(0));
                    } else if (countOfParameters > 1) {
                        Integer[] integerValues = new Integer[countOfParameters];
                        for (int kj = 0; kj < countOfParameters; kj++) {
                            integerValues[kj] = parameter.getIntValue(kj);
                        }
                        propertiesBuilder.addProperty(parameter.getName(), integerValues);
                    }
                    break;
                case LOCALDATE:
                    countOfParameters = parameter.getStringValueCount();
                    if (countOfParameters == 1) {
                        propertiesBuilder.addProperty(parameter.getName(), DateHelper.parseDate(parameter.getStringValue(0)));
                    } else if (countOfParameters > 1) {
                        LocalDate[] dateValues = new LocalDate[countOfParameters];
                        for (int kj = 0; kj < countOfParameters; kj++) {
                            dateValues[kj] = DateHelper.parseDate(parameter.getStringValue(kj));
                        }
                        propertiesBuilder.addProperty(parameter.getName(), dateValues);
                    }
                    break;
            }

Как видите, у меня та же логика, и единственное, что меняется, - это метод парсинга значения. Можно ли избавиться от дубликата кода? Я предполагаю, что возможно сделать некоторую Карту Функционального интерфейса Function, но не уверен, как это должно быть сделано. Есть предложения?

Ответы [ 3 ]

1 голос
/ 08 марта 2019

Если я вас правильно понял, то что-то вроде этого может быть:

Map<Type, Consumer<Builder>> map = Map.of(
     BOOLEAN, x -> x.add(BOOLEAN.parseBool()),
     STRING, x -> x.add(STRING.parseString())
);


map.get(type).accept(builder);
0 голосов
/ 08 марта 2019

Во-первых, отображение DOUBLE-to-Double и так далее можно выполнить в enum:

enum ValueType {
    DOUBLE(Double.class), // Or Double[].class
    BOOLEAN(Boolean.class),
    ...;

    public final Class<?> type;

    ValueType(Class<?> type) {
        this.type = type;
    }
}

Очевидно, код уже слишком специализирован, тогда как на самом деле точный тип не имеет значения. На этом уровне значение может быть просто объектом, и можно иметь Object[].

Следовательно, некоторый глубокий рефакторинг был бы идеальным.

ValueType vt = parameter.getType();
Class<?> t = vt.type;

Object array = Array.newInstance(t, countOfParameters);
// Actuallly Double[] or such.

int countOfParameters = parameter.getValueCount();
if (countOfParameters == 1) {
    propertiesBuilder.addProperty(parameter.getName(), parameter.getValue(0));
} else if (countOfParameters > 1) {
    Object array = Array.newInstance(t, countOfParameters);
    Class<?> componentT = array.getClass().getComponentType(); // == t

    Object[] values = new Object[countOfParameters];
    for (int kj = 0; kj < countOfParameters; kj++) {
        Array.set(array, kj, parameter.getValue(kj));
        values[kj] = parameter.getValue(kj);
    }
    propertiesBuilder.addProperty(parameter.getName(), values); // or array
}

Я добавил немного отражающего кода (Array), который, надеюсь, не нужен.

0 голосов
/ 08 марта 2019

Не уверен, что вам нужно, но вы можете использовать универсальные типы.

public class Element<T> {
    // T stands for "Type"
    private T t;

    public void set(T t) { this.t = t; }
    public T get() { return t; }
}

Вы можете использовать в своей функции:

public Object parse(Element t){
    if( t.get() instanceof Boolean )
        return parseBoolean(t);
    else if ( t.get() instanceof String )
        return parseString(t);
}


...