Если я правильно понимаю ваш вопрос, у вас есть подход, при котором вы зацикливаетесь на возможном templateFields
. Это не обязательно.
Поскольку каждое fieldArray[0]
сравнивается с некоторыми Constants
значениями и в случае дальнейшей обработки совпадения мы можем заменить цикл for на Map
. Его ключами являются возможные значения Constants
, а значениями являются сопоставители. Картограф - это BiFunction
, который принимает object
и значение fieldArray[1]
и возвращает для них сообщение типа String
.
Давайте начнем с картографов:
public class FieldToMessageMapper {
private static final Map<String, Function<String, String>> WORKINGTYPE_MESSAGE_MAPPER = new HashMap<>();
static {
WORKINGTYPE_MESSAGE_MAPPER.put("abc", fieldArray1 -> rightPad("a", Integer.parseInt(fieldArray1)));
WORKINGTYPE_MESSAGE_MAPPER.put("def", fieldArray1 -> rightPad("d", Integer.parseInt(fieldArray1)));
WORKINGTYPE_MESSAGE_MAPPER.put("DEFAULT", fieldArray1 -> rightPad("g", Integer.parseInt(fieldArray1)));
}
private static Map<String, BiFunction<MyObject, String, String>> MESSAGE_MAPPER = new HashMap<>();
static {
MESSAGE_MAPPER.put(Constants.WORKFLOW, (o, fieldArray1) -> rightPad(o.getFieldOne(), Integer.parseInt(fieldArray1)));
MESSAGE_MAPPER.put(Constants.WORKVOLUME, (o, fieldArray1) -> rightPad(o.getFieldTwo(), Integer.parseInt(fieldArray1)));
MESSAGE_MAPPER.put(Constants.WORKTYPE,
(o, fieldArray1) -> WORKINGTYPE_MESSAGE_MAPPER.getOrDefault(o.getFieldThree().toLowerCase(), WORKINGTYPE_MESSAGE_MAPPER.get("DEFAULT")).apply(fieldArray1));
}
public static Optional<String> map(MyObject o, String fieldArray0, String fieldArray1) {
return Optional.ofNullable(MESSAGE_MAPPER.get(fieldArray0.toLowerCase()))
.map(mapper -> mapper.apply(o, fieldArray1));
}
private static String rightPad(String string, int pad) {
// TODO right pad
return string;
}
}
Мы не возвращаем сам маппер. FieldToMessageMapper
предлагает метод map
, который выполняет отображение. Он возвращает Optional<String>
, который показывает, что результат может быть пустым, если нет сопоставления для ввода.
Чтобы получить отображение, независимое от регистра символов, все ключи String..toLowerCase()
.
Давайте продолжим общую обработку:
protected StringBuffer process(Collection<String> templateFields, MyObject object) {
StringBuffer message = new StringBuffer(1000);
for (String field : templateFields) {
String[] fieldArray = field.split(Constants.SEPARATOR);
String msg = FieldToMessageMapper.map(object, fieldArray[0], fieldArray[1])
.orElseThrow(() -> new IllegalArgumentException(String.format("Unsupported field %s", field)));
message.append(msg);
}
return message;
}
Я не знаю, как вам нужно обрабатывать пропущенные отображения. Я выбираю провал быстро, выбрасывая исключение.
Обратите внимание: StringBuffer
is
Потокобезопасная, изменяемая последовательность символов. Строковый буфер похож на
String
, но может быть изменено.
Если ваша обработка не многопоточная, вы можете использовать StringBuilder
. Если результат больше не изменяется, вы можете использовать String
.
Позвольте мне показать еще одну альтернативу, используя Stream
, которая возвращает String
:
protected String process(Collection<String> templateFields, MyObject object) {
return templateFields.stream()
.map(field -> field.split(Constants.SEPARATOR))
.map(fieldArray -> FieldToMessageMapper.map(object, fieldArray[0], fieldArray[1])
.orElseThrow(() -> new IllegalArgumentException(String.format("Unsupported field %s", Arrays.toString(fieldArray)))))
.collect(Collectors.joining());
}
Если я правильно понял код вопроса, должна быть следующая реализация Constants
:
public class Constants {
public static final String SEPARATOR = ",";
public static final String WORKFLOW = "field1";
public static final String WORKVOLUME = "filed2";
public static final String WORKTYPE = "field3";
}
РЕДАКТИРОВАТЬ:
Если вы хотите использовать конфигурационный подход, вы можете дополнительно разработать этот код, чтобы использовать конфигурацию Spring:
- Определите интерфейс
MessageMapper
, который имеет два метода: String getKey()
и String map(MyObject o, String fieldArray1)
. getKey()
возвращает значение Constants
, для которого сопоставитель обеспечивает сопоставление.
- Реализуйте каждый из вышеперечисленных
MESSAGE_MAPPER
, используя этот интерфейс.
- Добавьте
CommonMessageMapper
, у которого есть конструктор CommonMessageMapper(MessageMapper... messageMappers)
. messageMappers
должен быть помещен в Map<String, BiFunction<MyObject, String, String>> mappers
как: mappers.put(messageMapper.getKey(), messageMapper)
. Определите метод String map(MyObject o, String fieldArray0, String fieldArray1)
, который будет искать соответствующий MessageMapper mm
, используя fieldArray0
: MessageMapper mm = mappers.get(fieldArray0)
. Затем вызвать mm.map(o, feldArray1)
. (Вы также можете использовать здесь Optional
для обработки случая, когда нет соответствующего картографа.)
- Чтобы использовать конфигурацию Spring, все
MessageMapper
и CommonMessageMapper
должны быть аннотированы как Bean
или Component
. Конструктор CommonMessageMapper
должен быть аннотирован @Autowired
.
- Определите конфигурацию Spring (с использованием XML или как
@Configuration
), которая будет вводить желаемый MessageMapper
в CommonMessageMapper
и имеет заводской метод для такого CommonMessageMapper
.
- Используйте
CommonMessageMapper
вместо FieldToMessageMapper
выше.