Рассмотрим четыре варианта:
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");
Для меня каждый из 2, 3 и 4 адаптирован к разностной ситуации. Первый из них трудно любить по причинам, указанным в OP, и, как правило, является признаком дизайна, который подвергся некоторой ползучести и нуждается в некотором рефакторинге.
То, что я перечисляю как (2), хорошо, когда за «фабрикой» нет состояния, в то время как (3) - дизайн выбора, когда есть состояние. Я использую (2), а не (3), когда я не хочу беспокоиться о потоках и синхронизации, и мне не нужно беспокоиться об амортизации дорогостоящей установки для производства многих объектов. (3), с другой стороны, вызывается, когда реальная работа идет на создание фабрики (настройка из SPI, чтение файлов конфигурации и т. Д.).
Наконец, в чьем-то ответе упоминается опция (4), где у вас много маленьких неизменных объектов, и предпочтительным шаблоном является получение новостных из старых.
Обратите внимание, что я не являюсь членом "фан-клуба шаблонов" - конечно, некоторые вещи стоят того, чтобы имитировать, но мне кажется, что они начинают бесполезную жизнь, когда люди называют их и смешно головные уборы.