Вы можете создать набор магических строк и их соответствующих действий, а затем выполнить итерацию по ним вместо дублирования большого блока if-elseif-else
.
private static final Map<String, BiConsumer<YourObj, String>> configActions;
static {
Map<String, BiConsumer<YourObj, String>> tmp = new HashMap<>();
tmp.put("ServerAdmin", YourObj::setServerAdmin);
tmp.put("DocumentRoot", YourObj::setDocumentRoot);
// ...
configActions = Collections.unmodifiableMap(tmp);
}
public static YourObj load(List<String> directives) {
YourObj config = new YourObj();
directives.forEach(dir -> set(config, configActions, dir));
return config;
}
static <T> void set(T obj, Map<String, BiConsumer<T, String>> setters, String value) {
setters.entrySet().stream()
.filter(e -> value.contains(e.getKey()))
.findFirst()
.ifPresent(e -> e.getValue().accept(obj, value));
}
В общем, поиск магической строки с contains()
не очень надежный способ управления логикой. Если строка s
соответствует какому-либо формату, который гарантирует, что ваш поиск не приведет к ложным срабатываниям, рассмотрите возможность анализа этого формата и извлечения токена. И если входные строки не следуют какому-либо строгому формату, у вас есть высокий шанс попасть на неправильный токен первым. Например, если ваша конфигурация хранится в файле YAML, XML или JSON, используйте синтаксический анализатор YAML, XML или JSON соответственно.
В качестве примера рассмотрим, что произойдет, если у вас есть токены "LogFile" и "LogFileEncoding". Оба contain()
"LogFile", но только один является правильным соответствием.
Если вы используете Java 9 или новее, вы можете инициализировать Map
следующим образом:
private static final Map<String, BiConsumer<YourObj, String>> configActions = Map.of(
"ServerAdmin", YourObj::setServerAdmin,
"DocumentRoot", YourObj::setDocumentRoot,
// ...
);
Если у вас более десяти записей, вы можете использовать entry()
builder:
private static final Map<String, BiConsumer<YourObj, String>> configActions = Map.ofEntries(
Map.entry("ServerAdmin", YourObj::setServerAdmin),
Map.entry("DocumentRoot", YourObj::setDocumentRoot),
// ...
);
Эти методы были добавлены , чтобы устранить недостаток литералов коллекции и избежать проблем с существующими обходными путями.