명명 된 인수가 빌더 패턴을 대체합니까?


20

명명 된 및 선택적 인수를 지원하는 언어를 사용할 때 빌더 패턴이 더 이상 실용적이지 않습니까?

빌더 :

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

선택적 / 명명 된 인수 :

new Object(requiredA, requiredB, optionalA: "optional");

3
20 개의 선택적 인수를 어떻게 처리합니까? 빌더가 커질 때까지 해결해야 할 문제는 없습니다. 여기에 설명 된 시점에서 두 개의 생성자가 있습니다 (그리고 나는 그 작은 문제에 대한 빌더를 만들지 않을 것입니다).

1
선택적 인수를 사용하더라도 생성자에 인수가 두 개 이상인 경우 값 객체를 사용하여 구성을 캡슐화하는 것이 좋습니다. 유체 인터페이스 및 빌더도 마찬가지입니다. 3보다 큰 값은 값 객체로 대체됩니다.
Thomas Junk

답변:


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)
                    ...

특히 빌더 메소드 이름으로 암시 된 정보는 더 많은 매개 변수로 대체되어야하며 밀접하게 연관된 매개 변수 그룹에서 하나의 매개 변수를 잊어 버리기가 훨씬 쉽습니다. 실제로 프래그먼트 셰이더가 누락되었지만 찾을 필요가 없으면 알 수 없습니다.


물론 객체가 생성하는 데 1 ~ 5 개의 인수 만 사용하는 경우 명명 된 / 선택적 매개 변수의 유무에 관계없이 빌더 패턴을 포함시킬 필요가 없습니다.


나는 당신의 주장을 사지 않습니다. 빌더 메소드 이름이 너무 훌륭하면 매개 변수 이름에도 사용할 수 있습니다. 매개 변수가 밀접하게 관련되어 있으면 작은 객체 생성자에 넣으십시오.
user949300

@ user949300 요점에서 중요한 부분을 놓친 것 같습니다. 여기서 빌더 메소드는 선택적 매개 변수가 많은 경우 손실되는 매개 변수 간의 관계를 설명합니다. Ixrec의 빌더 예제에서 "health"및 "weight"는 논리적으로 파괴 가능한 본체 설정의 일부이지만 선택적 인수 버전에서는 관계가 손실됩니다.
Jules

1
선택적 매개 변수 중 하나가 (body : new DestructibleRigidBody (health, weight), ...) 인 경우는 아닙니다.
Weyland Yutani

@ 줄. Weyland가 말한 것-체중과 키에 대한 이름이 잘 알려진 생성자를 만드십시오.
user949300

8

Ixrec가 말한 것 외에도 매개 변수라는 생성자 또는 메서드를 사용하면 객체를 빌드하기 전에 여전히 수정할 수있는 구성 가능한 상태로 만들 수 없습니다. 이것은 빌더의 아름다움이며, 구성의 일부를 다른 방법이나 클래스에 모두 위임 할 수 있습니다.

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 빌더가 시스템을 가로 질러 이동 하지 않는 방법을 생각해보십시오 . 당신은 거대한 팬 아웃 요소를 가진 클래스를 강요받을 것입니다. 그리고 그것은 Thing을 만들기 위해 필요합니다. (물론, 수업에 모든 지식이 집중되어 있지 않다고 가정하면, 이것이 우리가 처음에 피하고 싶었던 것입니다.) 이제이 수업에 다른 책임이 있다면, 당신은 거대한 수업을 만들어서 S를 SOLID에서 깨고 있습니다. . 그것이 유일한 책임이라면, 당신은 스스로를 ThingBuilder로 만드는 것입니다.
Alpha

1

빌더로 수행중인 작업에 따라 다릅니다.

빌더를 사용하여 오브젝트 특성을 설정 (및 변경)하고 오브젝트 작성을 연기하는 경우 이름 지정된 매개 변수로 바꿀 수 있습니다.

빌더를 교체하면 @Ixrec이 언급 한 가독성 / 사용 상충 관계가있을 수 있습니다 (또는 작성하지 않은 경우 빌더로 수행중인 작업에 따라 다름).

그러나 빌더가 특성을 보유하는 것 이상을 수행하고 각 구성 단계에 논리가 포함 된 경우이를 대체 할 수 없습니다.

MockBuilder 는 명명 된 params로 대체 할 수없는 예입니다. 페이지에서 :

작성 단계의 논리는 명명 된 매개 변수로 대체 할 수 없습니다.


-5

변경 불가능한 오브젝트로 작업 할 때 빌더 패턴이 필수적입니다. 변경 불가능한 객체로 작업하면 많은 이점이 있습니다. 특히 동시 환경 (예 : 스레드)에서 프로그램을보다 강력하게 실행하는 경우


3
예, 빌더는 복잡한 불변 객체 (또는 심지어 변하기 쉬운 객체)로 작업하는 데 적합합니다. 사용하기 전에 객체가 일관된 상태인지 확인해야합니다. 즉 말했다 new Integer(42), new BigDecimal("42.000")그리고 new String("foobar")... 음, 빌더는 이러한 경우에 불필요하게 복잡 할 것 immutables 모든 생성자입니다. 따라서 생성자가 마찬가지로 작동 할 수있는 경우 불변으로 작업하는 빌더가 필수적 이지 않습니다 .

예, 생성자는 불변의 객체와 함께 사용할 수 있으며 거부되지 않습니다. 그러나 원래의 질문은 빌더 패턴이 선택적 인수와 별도로 실용적으로 사용되는지 여부였습니다. 내 대답은 이것을 명확히하는 것이 었습니다.
codedabbler

2
원래 질문은 불변의 객체에 대해서는 아무 것도 말하지 않습니다 . 명명 된 매개 변수와 빌더와의 관계에 대해 묻습니다. 당신의 대답은 빌더와 불변의 객체와의 관계에 관한 것입니다. 귀하의 답변이 질문에 어떻게 대답하는지 보는 데 어려움을 겪고 있습니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.