Рассмотрим четыре возможности:
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), где у вас много маленьких неизменяемых объектов, и предпочтительным шаблоном является получение новостей из старых.
Обратите внимание, что я не являюсь членом «фан-клуба выкройки» - конечно, некоторые вещи заслуживают подражания, но мне кажется, что они ведут бесполезную жизнь, когда люди дают им имена и забавные шляпы.