Заменяют ли именованные аргументы шаблон построителя?

20

При использовании языка, который поддерживает именованные и необязательные аргументы, шаблон компоновщика больше не имеет практического применения?

Строитель:

new Builder(requiredA, requiredB).setOptionalA("optional").Build();

Необязательные / именованные аргументы:

new Object(requiredA, requiredB, optionalA: "optional");
Павел Никонович
источник
3
Как вы обрабатываете 20 необязательных аргументов? Нет проблемы, которую Строитель должен решить, пока она не станет большой. В момент, который вы описали здесь, у вас есть два конструктора (и я бы не стал строить Builder для этой небольшой проблемы).
1
Даже с необязательными аргументами - если конструктор имеет более 2 аргументов, я предпочитаю использовать объект значения для инкапсуляции конфигурации. То же самое относится и к внутренним интерфейсам флюидов и компоновщику: все, что больше 3, будет заменено объектом-значением.
Томас Джанк

Ответы:

21

Строители наиболее полезны, когда вашему объекту нужно много аргументов / зависимостей, чтобы быть полезными, или если вы хотите разрешить много разных способов конструирования объекта.

Вдобавок ко всему, я могу представить, что кто-то может захотеть «построить» объекты в 3D-игре, подобной этой:

// Just ignore the fact that this hypothetical god class is coupled to everything ever
new ObjectBuilder(x, y, z).importBlenderMesh("./meshes/foo")
                          .syncWithOtherPlayers(serverIP)
                          .compileShaders("./shaders/foo.vert", "./shaders/foo.frag")
                          .makeDestructibleRigidBody(health, weight)
                          ...

Я бы сказал, что этот пример более читабелен с помощью методов компоновщика, которые я только что составил, чем с необязательными параметрами:

new Object(x, y, z, meshType: MESH.BLENDER,
                    meshPath: "./meshes/foo",
                    serverToSyncWith: serverIP,
                    vertexShader: "./shaders/foo.vert",
                    physicsType: PHYSICS_ENGINE.RIGID_DESTRUCTIBLE,
                    health: health,
                    weight: weight)
                    ...

В частности, информация, подразумеваемая именами методов компоновщика, должна быть заменена еще большим количеством параметров, и гораздо проще забыть об одном параметре в группе тесно связанных параметров. Фактически, фрагментный шейдер отсутствует, но вы не заметите этого, если не будете его искать.


Конечно, если ваш объект принимает от одного до пяти аргументов для создания, нет необходимости вовлекать шаблон компоновщика, независимо от того, были ли у вас именованные / необязательные параметры.

Ixrec
источник
Я не покупаю ваши аргументы. Если имена методов конструктора такие замечательные, вы можете использовать их и для имен параметров. Если параметры тесно связаны, поместите их в конструктор небольших объектов.
user949300
@ user949300 Я думаю, что вы упустили важную часть, которая заключается в том, что методы компоновщика здесь описывают отношения между параметрами, которые теряются, если у вас есть только несколько дополнительных параметров. В примере строителя Ixrec «здоровье» и «вес» явно логически являются частью настроек разрушаемого тела, но это отношение get l теряется в необязательном аргументе version.
Жюль
1
нет, если один из необязательных параметров (body: new DestructibleRigidBody (здоровье, вес), ...)
Weyland Yutani
@Jules. То, что сказал Вейланд, - сделать небольшого именитого конструктора для веса и роста.
user949300
8

В дополнение к тому, что сказал Ixrec, конструкторы или методы с именованными параметрами не позволят вам перевести ваш объект в готовое состояние, в котором он все еще может быть изменен перед его сборкой. В этом прелесть Builder, где вы можете делегировать части своей конструкции различным методам или классам в целом:

var myThingBuilder = new ThingBuilder("table");
myThingBuilder.setAttribute(Attributes.Legs, 4);

inventoryManager.setPrices(myThingBuilder);

// inventory manager
var availableCheapestMaterial = getMaterial();
myThingBuilder.setMaterial(availableCheapestMaterial);

По сути, вы также можете разбрасывать своего сборщика вокруг своей системы до тех пор, пока он не будет готов построить конечный объект, что позволит вам уменьшить объем знаний, необходимых вашему строителю-потребителю.

Альфа
источник
Я не понимаю ваш последний абзац. Если вы «бросаете своего сборщика вокруг системы, пока она не будет готова», он слишком много знает о системе. Ваш ThingBuilder знает об Атрибутах, загадочно изменен InventoryManager и знает о Материалах. Не понимаю, как это уменьшает знания.
user949300
@ user949300 Подумайте о том , как было бы без строителя путешествующего по всей системе. Вы были бы вынуждены иметь класс с огромным фактором разветвления, и это просто необходимо, чтобы построить Вещи. (Конечно, предполагая, что ваш класс не концентрирует все знания, это то, чего мы хотели бы избежать в первую очередь.) Теперь, если у этого класса есть какие-то другие обязанности, вы создаете огромный класс, разбивая S в SOLID. , Если это единственная ответственность, вы делаете из себя ThingBuilder.
Альфа
1

Это зависит от того, что вы делаете со строителем.

Если вы используете конструктор только для установки (и изменения) свойств объекта и (откладывания) создания объекта, его можно заменить именованными параметрами.

При замене компоновщика у вас может быть компромисс между удобочитаемостью и использованием, который имел в виду @Ixrec (или может не иметь его, это зависит от того, что вы делаете с компоновщиком).

Однако, если ваш конструктор делает больше, чем просто удерживает свойства, и каждый шаг построения включает в себя логику, его нельзя заменить.

MockBuilder - это пример, где его нельзя заменить именованными параметрами. Со страницы:

Логика шагов создания не может быть заменена именованными параметрами

rvazquezglez
источник
-5

Шаблон строителя необходим при работе с неизменяемыми объектами. Работа с неизменяемыми объектами имеет множество преимуществ, особенно в том, что ваша программа должна быть более устойчивой к выполнению в параллельной среде (т. Е. Потоках).

codedabbler
источник
3
Да, Builders отлично подходят для работы со сложными неизменяемыми объектами (или даже изменяемыми объектами - необходимо убедиться, что объект находится в согласованном состоянии, прежде чем его можно будет использовать). Тем не менее, new Integer(42), new BigDecimal("42.000")и new String("foobar")все конструкторы immutables , что ... ну, строитель был бы неоправданно сложным для этих случаев. Таким образом, сборщик не является обязательным для работы с неизменяемым, когда конструкторы могут работать так же хорошо.
Да, конструктор может использоваться с неизменяемыми объектами, что не отрицается. Но первоначальный вопрос заключался в том, имеет ли шаблон Builder какое-либо практическое применение, кроме необязательных аргументов, и я должен был уточнить это.
codedabbler
2
Оригинальный вопрос ничего не говорит о неизменных объектах. Он спрашивает об именованных параметрах и их связи со строителями. Ваш ответ о строителе и его отношении к неизменным объектам. Мне трудно понять, как ваш ответ отвечает на вопрос.