#java #java-8 #code-cleanup
#java #java-8 #очистка кода
Вопрос:
Мне нужно написать приведенный ниже код. Он принимает один тип перечисления и возвращает другое значение перечисления. Как удалить условие too much if else в коде и сделать его чистым?
private static QuestionType parseQuestionType(QuestionTypeInfo questionTypeInfo) {
if (questionTypeInfo instanceof OpenEndedTextQuestionTypeInfo) {
return QuestionType.OPEN_ENDED;
} else if (questionTypeInfo instanceof MultiChoiceQuestionTypeInfo) {
return QuestionType.MULTI_CHOICE;
} else if (questionTypeInfo instanceof MatrixSinglePerRowQuestionTypeInfo) {
return QuestionType.MATRIX_SINGLE_PER_ROW;
} else if (questionTypeInfo instanceof OpenEndedTextQuestionTypeInfo) {
return QuestionType.OPEN_ENDED;
} else if (questionTypeInfo instanceof MatrixMultiPerRowQuestionTypeInfo) {
return QuestionType.MATRIX_MULTI_PER_ROW;
} else if (questionTypeInfo instanceof MatrixSideBySideQuestionTypeInfo) {
return QuestionType.MATRIX_SIDE_BY_SIDE;
} else if (questionTypeInfo instanceof MatrixSpreadSheetQuestionTypeInfo) {
return QuestionType.MATRIX_SPREAD_SHEET;
} else if (questionTypeInfo instanceof DataListQuestionTypeInfo) {
return QuestionType.DATA_LIST;
} else if (questionTypeInfo instanceof FileUploadQuestionTypeInfo) {
return QuestionType.FILE_UPLOAD;
} else if (questionTypeInfo instanceof InteractiveSlidingScaleQuestionTypeInfo) {
return QuestionType.INTERACTIVE_SLIDING_SCALE;
} else if (questionTypeInfo instanceof NetPromoterQuestionTypeInfo) {
return QuestionType.NET_PROMOTER;
} else if (questionTypeInfo instanceof RankOrderQuestionTypeInfo) {
return QuestionType.RANK_ORDER;
} else if (questionTypeInfo instanceof PresentationHeaderQuestionTypeInfo) {
return QuestionType.PRESENTATION_HEADER;
} else if (questionTypeInfo instanceof PresentationHtmlQuestionTypeInfo) {
return QuestionType.PRESENTATION_HTML;
} else if (questionTypeInfo instanceof AutoIncrementQuestionTypeInfo) {
return QuestionType.AUTO_INCREMENT;
} else if (questionTypeInfo instanceof SingleChoiceQuestionTypeInfo) {
return QuestionType.SINGLE_CHOICE;
}
return null;
}
Комментарии:
1. использовать hasMap? с одним перечислением в качестве ключа, а другим в качестве значения?
2. Это отображение 1: 1?
3. По крайней мере, используйте
switch case
4. Это запах кода для использования
instanceof
. В большинстве случаев лучше иметь метод, который разные классы реализуют специально. (См. Ответ Ondra)
Ответ №1:
Вы можете использовать Map
, как предлагали другие, но я лично использовал бы делегирование, если это имеет смысл в вашем случае. В вашем QuestionTypeInfo
интерфейсе объявите абстрактный метод, getQuestionType
который возвращает экземпляр QuestionType
перечисления, и переопределите его во всех его реализациях с соответствующим значением.
interface QuestionTypeInfo {
QuestionType getQuestionType();
}
enum OpenEndedTextQuestionTypeInfo implements QuestionTypeInfo {
@Override
public QuestionType getQuestionType() {
return QuestionType.OPEN_ENDED;
}
}
Затем в parseQuestionType
методе просто используйте:
private static QuestionType parseQuestionType(QuestionTypeInfo questionTypeInfo) {
return questionTypeInfo.getQuestionType();
}
Комментарии:
1. Если этот рефакторинг базового интерфейса возможен, то это правильный путь, любое другое решение просто нарушает ООП, поскольку нужно знать о каждом подтипе базового интерфейса. Таким образом, реализующий класс должен сам решить, что
QuestionType
это такое. 1
Ответ №2:
Если вы можете гарантировать, что эти типы являются единственными, которые существуют, и что других подклассов не существует, вы могли бы создать сопоставление со следующей подписью:
Map<Class<? extends QuestionTypeInfo>, QuestionType> mapping;
А затем установите сопоставления. Например. вот так:
mapping.put(MatrixSinglePerRowQuestionTypeInfo.class, QuestionType.MATRIX_SINGLE_PER_ROW);
Затем вы можете выполнить простой поиск следующим образом:
return mapping.get(questionTypeInfo.getClass());
Хотя это работает только тогда, когда, например, MatrixSinglePerRowQuestionTypeInfo
является классом без дополнительного подкласса. Поскольку Map
использует equals
метод внутри, чтобы проверить, существует ли данный ключ. Посмотрите этот упрощенный пример, который нарушит мою предложенную логику (но будет работать с вашей существующей !!):
// create a subclass
class SomeSubClass extends MatrixSinglePerRowQuestionTypeInfo { ... }
// initialize the mapping
mapping.put(MatrixSinglePerRowQuestionTypeInfo.class, Foo.BAR);
// in your lookup
mapping.get(MatrixSinglePerRowQuestionTypeInfo.class); // returns Foo.BAR as expected
mapping.get(SomeSubClass.class); // returns null??