Tener funciones auxiliares estáticas para crear el argumento del constructor es una solución perfectamente sensata, pero estas funciones están limitadas en las operaciones que pueden realizar, ya que deben producir exactamente un argumento cada una y no pueden comunicarse entre sí.
En el caso más general en el que desea adaptar una interfaz Constructor(A, B, C)
a una interfaz más utilizable Constructor(X, Y)
, puede definir un constructor auxiliar privado que lleve un privado ArgumentObject
y encadene al constructor existente. El constructor más utilizable se encadena al constructor auxiliar mediante una función auxiliar estática para crear el objeto de argumento:
class Constructor {
// constructor you want to wrap
public Constructor(A a, B b, C c) { ... }
// better constructor you are defining
public Constructor(X x, Y y) { this(createArgumentObject(x, y)); }
// helper constructor using an ArgumentObject
private Constructor(ArgumentObject ao) { this(ao.a, ao.b, ao.c); }
// helper to create the argument object
private static ArgumentObject createArgumentObject(X x, Y y) { ... }
private static class ArgumentObject { ... }
}
En lenguajes que no tienen encadenamiento de constructor dentro de la misma clase (como C ++ 03), tendría que definir una subclase intermedia para el constructor auxiliar.
Sin embargo, esta técnica es simplemente una generalización de su uso de funciones estáticas en los argumentos del constructor. Las otras soluciones que ha propuesto tienen varios inconvenientes, por lo que los evitaría a menos que haya una muy buena razón para preferirlos:
implementar buenos constructores requiere mucho esfuerzo por muy poco valor. Si el nuevo constructor es lo suficientemente simple, puede prescindir de un constructor. Suponiendo que la clase que está ajustando realiza una validación sólida, puede hacer público el objeto de argumento para que los argumentos puedan pasarse utilizando el Constructor(new Constructor.Arguments {{ foo = 42; bar = baz; }})
idioma.
el uso de variables estáticas que se calculan en un bloque inicializador estático tiene sentido para datos verdaderamente estáticos, pero se debe tener cuidado para evitar el estado global. A menos que la inicialización sea muy simple, debe usar funciones estáticas para inicializar estas variables para que la inicialización sea comprobable. Ahora, la única ventaja sobre el uso directo de métodos estáticos es que los valores solo se calculan una vez y se reutilizan para todas las inicializaciones.
Como su pregunta indica que estas inicializaciones podrían ser más complejas, el uso de bloques inicializadores estáticos es un gran no-no si la capacidad de prueba es importante para usted. (Si no es así, tiene problemas más urgentes).