Предполагая, что вы эффективно применяете значения по умолчанию, обычно лучше всего иметь один «полный» конструктор и заставить другие вызывать его.Например:
public Foo(String name)
{
// Default the description to null
this(name, null);
}
public Foo(String name, String description)
{
this.name = name;
this.description = description;
}
Вы по-прежнему сталкиваетесь с большими перебоями с точки зрения перегруженных конструкторов, но по крайней мере каждый из этих «дополнительных» конструкторов не содержит реального кода - просто вызов другого конструктора.Если возможно, соедините конструкторы вместе, чтобы значение по умолчанию для любого конкретного значения было указано только в одном месте, или используйте константу.Таким образом, вы получаете согласованность.
Другой вариант - использовать «объект параметра» по шаблону компоновщика - создать другой класс, единственная цель которого - хранить данные для параметров конструктора.Это должно быть изменяемым, с установщиками для всех различных значений.Часто бывает полезно, чтобы установщики возвращали компоновщик, поэтому вы можете использовать:
FooParameters parameters = new FooParameters()
.setName("some name")
.setDescription("some description");
// Either a constructor call at the end, or give FooParameters
// a build() or create() method
Foo foo = new Foo(parameters);
Это особенно полезно, если основной тип, который вы создаете, является неизменяемым типом - это означает, что вы можете применять условную логику ввызывающий код для установки некоторых параметров, но не других.Сама инфраструктура Java использует этот подход в ProcessBuilder
, хотя лично я не заинтересован в том, как он перегружает имена методов, чтобы либо вернуть значение, либо установить значение в зависимости от того, предоставлен ли аргумент: (
Обратите внимание на комментарий над вызовом конструктора в последнем фрагменте - если ваш вспомогательный класс полезен только для создания объектов одного типа, вы можете назначить ему дополнительный метод (build
, create
, start
, независимо от того, чтонаиболее подходящим), чтобы занять место вызова конструктора. Это позволяет вам быстро построить весь конечный объект.
Один вариант в реализации Java шаблона компоновщика - использовать вложенный тип, например
Foo foo = new Foo.Builder().setName(...).setDescription(...).build();
Это позволяет избежать загрязнения вашего пакета другим классом, который only полезен для создания экземпляров Foo
.