Rozważ cztery możliwości:
new Immutable(one, fish, two, fish, red, fish, blue, fish); /*1 */
params = new ImmutableParameters(); /*2 */
params.setType("fowl");
new Immutable(params);
factory = new ImmutableFactory(); /*3 */
factory.setType("fish");
factory.getInstance();
Immutable boringImmutable = new Immutable(); /* 4 */
Immutable lessBoring = boringImmutable.setType("vegetable");
Dla mnie każdy z 2, 3 i 4 jest dostosowany do innej sytuacji. Pierwszy z nich jest trudny do pokochania z powodów przytoczonych przez OP i ogólnie jest objawem projektu, który przeszedł pewne pełzanie i wymaga refaktoryzacji.
To, co wymieniam jako (2), jest dobre, gdy za „fabryką” nie ma stanu, podczas gdy (3) jest projektem z wyboru, gdy istnieje stan. Używam (2) zamiast (3), gdy nie chcę martwić się wątkami i synchronizacją, i nie muszę martwić się o amortyzację kosztownej konfiguracji podczas produkcji wielu obiektów. (3), z drugiej strony, jest wywoływane, gdy prawdziwa praca idzie do budowy fabryki (ustawienie z SPI, odczyt plików konfiguracyjnych itp.).
Wreszcie, czyjaś odpowiedź wspomniała o opcji (4), w której masz wiele małych niezmiennych obiektów, a preferowanym wzorcem jest pobieranie wiadomości ze starych.
Zwróć uwagę, że nie jestem członkiem „fanklubu wzorców” - oczywiście, niektóre rzeczy są warte naśladowania, ale wydaje mi się, że gdy ludzie nadadzą im imiona i zabawne kapelusze, zaczynają żyć własnym życiem.