34

ビルダーパターンは不変オブジェクトを作成するのに人気がありますが、ビルダーを作成するにはプログラミングのオーバーヘッドがあります。だから、なぜ単純に構成オブジェクトを使用しないのだろうか。

ビルダーの使用法は次のようになります。

Product p = Product.Builder.name("Vodka").alcohol(0.38).size(0.7).price(17.99).build();

これが非常に読みやすく簡潔であることは明らかですが、ビルダーを実装する必要があります。

public class Product {

    public final String name;
    public final float alcohol;
    public final float size;
    public final float price;

    private Product(Builder builder) {
        this.name = builder.name;
        this.alcohol = builder.alcohol;
        this.size = builder.size;
        this.price = builder.price;
    }

    public static class Builder {

        private String name;
        private float alcohol;
        private float size;
        private float price;

        // mandatory
        public static Builder name(String name) {
            Builder b = new Builder();
            b.name = name;
            return b;
        }

        public Builder alcohol(float alcohol) {
            this.alcohol = alcohol;
            return.this;
        }

        public Builder size(float size) {
            this.size = size;
            return.this;
        }

        public Builder price(float price) {
            this.price = price;
            return.this;
        }

        public Product build() {
            return new Product(this);
        }

    }

}

私の考えは、次のような単純な構成オブジェクトを使用してコードを減らすことです。

class ProductConfig {

        public String name;
        public float alcohol;
        public float size;
        public float price;

        // name is still mandatory
        public ProductConfig(String name) {
            this.name = name;
        }

}

public class Product {

    public final String name;
    public final float alcohol;
    public final float size;
    public final float price;

    public Product(ProductConfig config) {
        this.name = config.name;
        this.alcohol = config.alcohol;
        this.size = config.size;
        this.price = config.price;
    }

}

使用法:

ProductConfig config = new ProductConfig("Vodka");
config.alcohol = 0.38;
config.size = 0.7;
config.price = 17.99;
Product p = new Product(config);

この使用法にはさらに数行が必要ですが、非常に読みやすくなっていますが、実装ははるかに単純であり、ビルダーパターンに精通していない人にとっては理解しやすいかもしれません。ちなみに、このパターンの名前はありますか?

私が見落としていた構成アプローチの欠点はありますか?

4

9 に答える 9

20

ビルダーパターンはデカップリングを改善します-あなたの製品はインターフェースでありえ、実装(または場合によっては実装)について知っている唯一のクラスはビルダーです。ビルダーがインターフェースも実装している場合は、これをコードに挿入して、デカップリングをさらに増やすことができます。

この分離は、コードがより保守しやすく、テストが容易であることを意味します。

于 2010-08-03T08:35:56.987 に答える
9

すでに指摘されているように、ビルダーパターンのいくつかの利点が失われています(新しいビルダーは、クリーンなビルダーと比較して、醜く、保守が難しく、詳細が漏れています)。

しかし、私が最も見逃しているのは、ビルダーパターンを使用して「流暢なインターフェイス」と呼ばれるものを提供できることです。

これの代わりに:

ProductConfig config = new ProductConfig("Vodka");
config.alcohol = 0.38;
config.size = 0.7;
config.price = 17.99;
Product p = new Product(config);

できるよ:

ProductFactory.create()
    .drink("Vodka")
    .whereAlcohoolLevelIs(0.38)
    .inABottleSized(0.7)
    .pricedAt(17.99)
    .build();

誰もが流暢なインターフェースを好むわけではありませんが、それらは間違いなくビルダーパターンの非常に優れた使用法です(すべての流暢なインターフェースはビルダーパターンを使用する必要がありますが、すべてのビルダーパターンが流暢なインターフェースであるとは限りません)。

Googleコレクションのようないくつかの優れたJavaコレクションは、「流暢なインターフェース」を非常に自由に、そして非常にうまく利用しています。私はあなたの「タイプしやすい/文字が少ない」アプローチよりもいつでもこれらを選びます:)

于 2010-08-03T09:34:48.210 に答える
5

構成パターンとビルダーパターンは機能的に同等です。どちらも同じ問題を解決します-

  • 複数のコンストラクター署名の必要性を排除します

  • 建設中にのみフィールドを設定できるようにする

  • 消費者が気になる値のみを設定し、他の値には論理的なデフォルトを設定できるようにする

検証を行うメソッドでのみ状態を設定できるようにしたり、カプセル化されたロジックで状態を設定したりするなど、これらのパターンの1つで実行したいことはすべて他のパターンでも実行できます。唯一の本当の違いは、newキーワードを使用してオブジェクトを作成するのが好きなのか、メソッドを呼び出すのが好きなのかということです.build()

于 2017-08-16T22:55:18.513 に答える
4

パターンでどのような問題を解決しようとしていますか?ビルダーパターンは、大量の異なるコンストラクターや非常に長いコンストラクターを防ぐために、多くの(オプションの)パラメーターを持つオブジェクトに使用されます。また、構築中にオブジェクトを一貫した状態(javabeanパターンに対して)に保ちます。

ビルダーと「構成オブジェクト」(良い名前のように感じます)の違いは、コンストラクターまたはゲッター/セッターによって同じパラメーターでオブジェクトを作成する必要があることです。これは、a)コンストラクターの問題を解決しないか、b)構成オブジェクトを一貫性のない状態に保ちます。構成オブジェクトの状態に一貫性がない場合でも、実際には問題はありませんが、未完成の構成オブジェクトをパラメーターとして渡すことができます。[ファントムタイプへのミシッドリンクはこの問題を解決するようですが、それでも読みやすさが失われます(new Foo<TRUE,TRUE, TRUE, FALSE, TRUE>ちょっとひどいです)。]これがビルダーパターンの大きな利点です。オブジェクトを作成する前にパラメータを検証でき、任意のサブタイプを返すことができます(動作工場のように)。

構成オブジェクトは、すべて必須のパラメーターのセットに対して有効です。このパターンは、以前に.NETまたはJavaで何度も見たことがあります。

于 2010-08-03T09:03:48.070 に答える
2

個人的には、ビルダーパターンは、これらのオブジェクトが実際に使用されている場所で、よりクリーンなコードを提供していると感じています。一方、ゲッター/セッターがないことは、キャメルケースのゲッター/セッターを期待する多くのフレームワークではあまり使用できません。これは私が感じる深刻な欠点です。

私がゲッター/セッターで気に入っているのは、自分が何をしているのかをはっきりと確認できることです。ビルダーを使用すると、ここで直感的な明瞭さが少し失われているように感じます。

多くの人が特定の本を読んだこと、そして今や突然、ビルダーパターンが新しいiPhoneであるかのように誇大宣伝を楽しんだことを私は知っています。しかし、私はアーリーアダプターではありません。私は「新しい方法」を使用するのは、パフォーマンス、メンテナンス、コーディングなど、どの領域でも大幅な時間の節約になることが本当に証明されている場合のみです。

私の実際の経験では、通常、ゲッター/セッターとコンストラクターの方が優れています。これらのPOJOをあらゆる目的で再利用できます。

Config Objectの目的はわかりますが、ビルダーよりもさらにオーバーヘッドが大きいと思います。何のためにあるのでしょうか。セッターの何が問題になっていますか?

たぶん、WITH句を発明する必要があります:例、あなたが持っているとしましょう

public Class FooBar() {
    private String foo;

    public void setFoo(String bar) { 
      this.foo = bar; 
    }

    public String getFoo() { 
        return this.foo; 
    }
}

public static void main(String []args) {

 FooBar fuBar = new FooBar();
 String myBar;

 with fuBar {
    setFoo("bar");
    myBar = getFoo(); 
 }
}

ああ、わかりません...これにより、内部クラスの煩わしさがなくても、コードの記述が速くなる可能性があると思います。Oracle Javaの第一人者と関係のある人はいますか?

ビルダーでオブジェクトを使用するほどきれいには見えませんが、ビルダーの構築時間を節約できます。そして、フレームワークで使用できる通常のpojo/beanとしてクラスを引き続き使用できます...

あなたたちは実際にこの条項が好きですか、それともそれはむしろ悪いと思いますか?乾杯

于 2012-09-18T14:18:33.037 に答える
2

builder-builderの使用を検討しましたか?

ビルダー(「With」のような接頭辞が付いている)は、より自然に/流暢に読むと思います。

于 2010-08-03T09:16:43.520 に答える
1

IMO、検証などがある場合、ビルダーパターンははるかに堅牢です。

あなたの場合のビルダーパターンは、次のように変更できます。

Product p = new ProductBuilder("pName").alcohol(0.38).size(0.7).price(17.99).build();

このbuild()メソッドは、ビルダーに必要なすべての検証作業を実行できます。ビルダーパターンには、いくつかの設計上の利点もあります(これらすべてがあなたの場合には当てはまらないかもしれません)。詳細については、この質問を確認してください

于 2010-08-03T08:37:21.523 に答える
0

主な欠点は、それがジョシュアの本に載っていないため、ドローンが頭を包むことができないことです。

単純な値オブジェクトを使用して、関数(/ method /コンストラクター)が必要とする複数の引数を保持しています。これには何の問題もありません。これは長年にわたって行われてきました。オプションのパラメータに名前を付けていない限り、このような回避策を考案する必要があります。これは残念なことであり、太陽の神々からの素晴らしい発明ではありません。

本当の違いは、フィールドを直接公開することです。Joshuaは、パブリックな可変フィールドを持つことは決してありませんが、彼は、ほとんどがモロンである何百万もの人々によって使用されるAPIを作成します。また、APIは、今後数十年にわたって安全に進化する必要があり、設計のためだけに何ヶ月も割り当てることができます。簡単なクラス

それをエミュレートするのは誰ですか?

于 2010-08-03T17:24:37.887 に答える
-1

パブリックフィールドは使用しないでください。保護またはプライベートを使用してください。アクセスするには、カプセル化を維持するためにゲッターとセッターを使用する必要があります。

于 2010-08-03T08:38:53.857 に答える