Это два разных подхода. Сделки разные. Вы должны использовать и адаптировать шаблон в соответствии с вашими потребностями и ваш контекст, а не в соответствии с жестким правилом ...
Используя конструктор, как это:
Product p = new Product(builder);
позволяет создать построитель и повторно использовать его. Если вам нужно повторно использовать конструктор или создать конструктор в другом классе, это хорошая реализация. Вы открываете свой API, потому что вам это нужно.
Недостатки решения - это не прямой способ создания вашего объекта.
Что касается качества дизайна и зависимости, я думаю, что это ложная проблема. Да с открытым конструктором для Продукта вы создаете общественную зависимость между Продуктом и Строителем, и вы раскрываете конструктор продукта. Но если в конструкторе Product вы отправите экземпляру компоновщика задачу для создания Продукта, будет ли соединение связывать код менее гибким? Никогда.
Кроме того, реальная муфта находится в конструкции продукта, так как строитель использует свойства зеркала для создания объекта Product. Таким образом, реальное и сильное сцепление останется тем, что происходит: эти два класса должны работать вместе и должны выглядеть.
Использование строитель, как это:
Product p = builder.part1()
.part2()
.build();
не позволяет повторно использовать построитель, но более прямо использовать для клиента класса, и это открывает как минимум зависимости между Builder к продукту. Если вам не нужно повторно использовать построитель или создать конструктор в другом классе, это лучше всего, так как вы не открываете свой API бесполезным способом.
Итак, в фактах, оба решения находятся рядом. Я бы использовал решение с конструктором, если я должен повторно использовать построитель, или мне нужно создать конструктор в другом классе, и я бы использовал решение без конструктора, если это не было необходимо.
Я также понял, что подход 2. не будет работать, если 'Product' является интерфейсом. Вам нужно будет ввести метод 'construct()', то есть вы могли бы просто пойти по пути 'Builder.build(). –