Самый простой способ передачи большого количества параметров в Java
Мой основной язык - TypeScript, и он позволяет упаковывать большое количество аргументов в объекты:
function initializeApplication(options: {
projectBuildingMode: string,
enableDebugging: boolean,
projectType: string,
// ... и ещё несколько десятков
}): void { }
Что есть в Java максимально близкое по концепции к приведённому выше коду?
Проблема
void initializeApplication(String projectBuildingMode, Boolean enableDebugging, String projectType, /* и ещё пару десятков ... */)
Что, если мы заходим добавить в середину один-два параметра? Придётся переписывать места вызова этого метода.
Ответы (3 шт):
Вы можете создать класс который можно использовать в качестве аргумента и в случае добавления полей, вам нужно будет изменять только его, если вам не нужно будет модифицировать под новые поля другие функции, то при помощи конструкторов, значений по умолчанию и get/set вы можете избежать переписывания старых кусков.
Можно попробовать использовать @Builder от ломбока, как подсказал @Miron или воспользоваться перечислением с помощью type... Ниже привел пример кода
@Builder
@ToString
public class Animal {
private String cat;
private String dog;
private String cow;
private String giraffe;
private String bear;
}
class Main {
public static void main(String[] args) {
Animal animal = Animal
.builder()
.bear("Медведь")
.cat("Мурка")
.dog("Шарик")
.build();
printAnimal(animal);
printAnimal("Медведь", " Кот", " Бык");
}
private static void printAnimal(Animal animal) {
System.out.println(animal.toString());
}
private static void printAnimal(String... value) {
Stream.of(value).forEach(System.out::print);
}
}
На основе подсказок @Дмитрий, @IvanDyominov и @Miron разработал такой билдер:
public class Person {
private String familyName;
private String givenName;
public Person(ParametersObject parametersObject) {
parametersObject.initializeSpecifiedFields(this);
}
public static ParametersObject parametersObject() {
return new Person.ParametersObject();
}
public static class ParametersObject {
private String familyName;
private String givenName;
public void initializeSpecifiedFields(Person person) {
person.familyName = this.familyName;
person.givenName = this.givenName;
}
public ParametersObject setFamilyName(String familyName) {
this.familyName = familyName;
return this;
}
public ParametersObject setGivenName(String givenName) {
this.givenName = givenName;
return this;
}
}
}
Теперь конструировать Person можно так:
new Person(Person.parametersObject()
.setFamilyName("Jonson")
.setGivenName("John")
);
Недостатки решения
- Пока не знаю, как обязать других программистов, которые будут создавать инстанс
Person, инициализировать обязательные поля. В теории, если можно как-то обязать вызвать метод, то проблема решаема. - Если понадобится облепить класс Person сеттерами, то они могут быть один в один с сеттерами с
ParametersObject(если мы пожелаем цепную API). Разница лишь в том, что они возвращают разныйthis. Создавать абстрактный класс, общий дляPersonиParametersObjectне хочется - хотелось бы, чтобы всё было инкапсулировано в одном классе (то есть, чтобы сущность Person была основополагающей и самостоятельной).
Конструктивная критика решения приветствуется!