Я бы порекомендовал вам рассмотреть шаблон builder в таком случае. Вы гарантированно получите действительный объект без огромного списка параметров.
ОП был обновлен, чтобы отклонить шаблон построителя, но, похоже, он основан на недоразумении. Тот факт, что шаблон Builder существует, не отменяет принудительное применение всех параметров.
Рассмотрим следующий объект:
public class SomeImmutableObject {
private String requiredParam1;
private String requiredParam2;
//etc.
private SomeImmutableObject() { //cannot be instantiated outside the class }
public static class Builder {
private SomeImmutableObject instance;
public Builder() { instance = new SomeImmutableObject();
public Builder setParameter1(String value) {
instance.requiredParam1 = value;
return this;
}
//etc for each parameter.
public SomeImmutableObject build() {
if (instance.requiredParam1 == null || instance.requiredParam2 == null /*etc*/)
throw new IllegalStateException("All required parameters were not supplied.");
return instance;
}
}
}
Обратите внимание, что вы можете сделать в основном то же самое, сделав пакет полей закрытым и поместив компоновщик в тот же пакет.
И если по какой-то причине вы не можете этого сделать, у вас все еще может быть конструктор с 10 параметрами, а затем только Builder будет вызывать этот конструктор, чтобы его было проще использовать API.
Таким образом, для всех заявленных требований шаблон Builder работает просто отлично. Тот факт, что требуются все 10 параметров, вовсе не дисквалифицирует шаблон Builder. Если есть какая-то другая потребность, которую шаблон не удовлетворяет, уточните.
Редактировать: ОП добавил комментарий (довольно давно, но я только что получил возражение по этому вопросу, поэтому я только увидел его сейчас) с интересным вопросом: как вы проверяете примитив в более поздний момент времени?
Есть несколько способов обойти эту проблему, в том числе защитный логический, но я бы предпочел использовать объект типа Double следующим образом:
private Double doubleForPrimitive;
public Builder setDouble(double d) {
doubleForPrimitive = d;
}
public SomeImmutableObject build() {
if(doubleForPrimitive != null) {
instance.doubleParam = doubleForPrimitive;
} else {
throw new IllegalArgumentExcepion("The parameter double was not provided");
}
//etc.
}
Следует отметить, что если вам нужна истинная поточно-ориентированная неизменяемость, в которой все поля неизменяемого объекта являются окончательными, для этого требуется больше шаблона (хранение переменных внутри компоновщика и передача их частному конструктору неизменяемого объекта). ), но подход все еще чист с точки зрения клиентского кода.