Ter funções auxiliares estáticas para criar o argumento do construtor é uma solução perfeitamente sã, mas essas funções são limitadas em quais operações elas podem executar, pois devem produzir exatamente um argumento cada e não podem se comunicar.
No caso mais geral em que você deseja adaptar uma interface Constructor(A, B, C)
a uma interface mais utilizável Constructor(X, Y)
, é possível definir um construtor auxiliar particular que leva um privado ArgumentObject
e acorrenta ao construtor existente. O construtor mais utilizável acorrenta ao construtor auxiliar através de uma função auxiliar estática para criar o 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 { ... }
}
Em linguagens que não têm encadeamento de construtor na mesma classe (como C ++ 03), você teria que definir uma subclasse intermediária para o construtor auxiliar.
No entanto, essa técnica é apenas uma generalização do uso de funções estáticas nos argumentos do construtor. As outras soluções que você propôs têm várias desvantagens, e é por isso que eu as evito, a menos que haja uma boa razão para preferi-las:
implementar bons construtores exige muito esforço por muito pouco valor. Se o novo construtor for bastante simples, você poderá ficar sem um construtor. Supondo que a classe que você está agrupando realiza validação sólida, você pode tornar público o objeto de argumento para que os argumentos possam ser transmitidos usando o Constructor(new Constructor.Arguments {{ foo = 42; bar = baz; }})
idioma.
o uso de variáveis estáticas calculadas em um bloco inicializador estático faz sentido para dados realmente estáticos, mas é preciso ter cuidado para evitar o estado global. A menos que a inicialização seja muito simples, você deve usar funções estáticas para inicializar essas variáveis para que a inicialização seja testável. Agora, a única vantagem sobre o uso direto de métodos estáticos é que os valores são calculados apenas uma vez e reutilizados para todas as inicializações.
Como sua pergunta indica que essas inicializações podem ser mais complexas, o uso de blocos estáticos de inicialização é um grande não-não se a testabilidade for importante para você. (Caso contrário, você tem problemas mais urgentes.)