名前付き引数はビルダーパターンを置き換えますか?


20

名前付き引数とオプションの引数をサポートする言語を使用する場合、ビルダーパターンは実用的ではなくなりますか?

ビルダー:

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

オプション/名前付き引数:

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

3
20個のオプション引数をどのように処理しますか?Builderが大きくなるまで解決する必要のある問題はありません。ここで説明した時点で、2つのコンストラクターがあります(その小さな問題のためにBuilderをビルドすることはありません)。

1
オプションの引数があっても-コンストラクタに3つ以上の引数がある場合、値オブジェクトを使用して構成をカプセル化することをお勧めします。流体のインターフェイスとビルダーについても同じことが言えます。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)
                    ...

特に、ビルダーメソッド名によって暗示される情報は、さらに多くのパラメーターに置き換えられる必要があり、密接に関連するパラメーターのグループ内の1つのパラメーターを忘れやすくなります。実際、フラグメントシェーダーはありませんが、それを探すことを知らない限り、そのことに気付かないでしょう。


もちろん、オブジェクトの構築に1〜5個の引数のみを使用する場合、名前付き/オプションのパラメーターがあるかどうかに関係なく、ビルダーパターンを取得する必要はありません。


私はあなたの議論を買いません。ビルダーメソッド名が非常に素晴らしい場合は、パラメーター名にも使用できます。パラメーターが密接に関連している場合は、それらを小さなオブジェクトコンストラクターに入れます。
user949300

@ user949300ポイントの重要な部分を見逃したと思います。つまり、ここでのビルダーメソッドは、オプションのパラメーターがたくさんある場合に失われるパラメーター間の関係を記述するということです。Ixrecのビルダーの例では、「健康」と「体重」は明らかに論理的に破壊可能なボディ設定の一部ですが、その関係はオプションの引数バージョンでは失われます。
ジュール

1
オプションパラメーターの1つが(body:new DestructibleRigidBody(health、weight)、...)でない場合
ウェイランドユタニ

@ジュール。ウェイランドが言ったこと-体重と身長のために、ちょっとした名前のついたコンストラクターを作りましょう。
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は属性について知っており、在庫マネージャによって不思議な変更が加えられ、マテリアルについても知っています。それがどのように知識を減少させているのか見ないでください。
user949300

@ user949300 ビルダーがシステム内を移動しないとどうなるかを考えてください。あなたは巨大なファンアウト要因を持つクラスを持つことを余儀なくされるでしょう、そしてそれは事を構築するために必要なだけです。(もちろん、あなたのクラスがすべての知識に集中していないと仮定すると、そもそもこれは避けたいものです)。 。それが唯一の責任であれば、あなたは自分自身をThingBuilderにしています。
アルファ

1

それはあなたがビルダーで何をしているかに依存します。

ビルダーを使用してオブジェクトのプロパティを設定(および変更)し、オブジェクトの作成を延期する場合は、名前付きパラメーターに置き換えることができます。

ビルダーを置き換えると、@ Ixrecが読みやすさ/使用量のトレードオフが生じる可能性があります(または、ない場合があります。ビルダーで何をしているかによって異なります)。

ただし、ビルダーがプロパティを保持するだけではなく、各構築ステップにロジックが含まれる場合、それを置き換えることはできません。

MockBuilderは、名前付きパラメーターに置き換えることができない例です。ページから:

作成ステップのロジックを名前付きパラメーターに置き換えることはできません


-5

不変オブジェクトを操作する場合、ビルダーパターンは不可欠です。不変オブジェクトを操作することには、多くの利点があります。特に、並行環境(スレッドなど)でプログラムをより堅牢に実行する場合に役立ちます。


3
はい、ビルダーは複雑な不変オブジェクト(または可変オブジェクトでも使用できます-オブジェクトを使用するには、そのオブジェクトが一貫した状態にあることを確認する必要があります)。とは言ってもnew Integer(42)new BigDecimal("42.000")new String("foobar")はすべて不変のコンストラクタであり、...これらのインスタンスではビルダーは不必要に複雑になります。したがって、コンストラクターが同様に機能する場合、不変物を使用するのにビルダーは必須ではありません。

はい、コンストラクタは不変オブジェクトで使用できますが、拒否されていません。しかし、元の質問は、Builderパターンにオプションの引数以外の実用的な用途があるかどうかであり、私の回答はこれを明確にすることでした。
-codedabbler

2
元の質問は、不変オブジェクトについては何も述べていません。名前付きパラメーターと、ビルダーとのそれらの関係について尋ねています。あなたの答えは、ビルダーと不変オブジェクトとの関係についてです。あなたの答えが質問にどのように答えるかを見るのに苦労しています。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.