3

私は最近、研究グループでデザインパターンを研究してきましたが、ビルダーパターンは、多くの(場合によってはオプションの)パーツで構成される複雑なオブジェクトを作成するのに非常に役立つことがあることを理解しました。

しかし、ビルダーがやりすぎているポイントはありますか?オブジェクトの多くの異なる組み合わせを持つクラスがあるとしましょう。何十もの異なるビルダーを作成する代わりに、それに適した別のパターンがありますか?完全に特定のビルダーを作成しないことで、必要なビルダーの数を減らすことは可能ですか?

私の研究グループと私が何度も訪れた例は、自動車会社のWebサイトなどの自動車メーカーでした。どの自動車会社にも数十台の車があり、それぞれにさまざまな機能、色、追加機能などがあります。私が理解しているように、ビルダーは作成しているオブジェクトに固有である必要があるため、この例にビルダーパターンを適用すると数百台になります。 「RedSUVWithSunroofBuilder」、「BlueSUVWithSunroofBuilder」、「RedSUVBuilder」などのようなビルダー。

ビルダーパターンを使用して、作成する必要のあるビルダーの数を減らすためにこれらの値の一部を渡すことができなかった理由はありますか?たとえば、RedSUVWithSunroofBuilderまたはBlueSUVWithSunroofBuilderを使用する代わりに、SUVWithSunroofBuilder( "Red")およびSUVWithSunroofBuilder( "Blue")を実行するビルダーパターンに適合していますか、それとも別のパターンに適合していますか?

4

5 に答える 5

5

さて、私は数ヶ月前に同じ質問を疑問に思いました、そして私は呼ばれる新しいデザインパターンを思いつきますstep builder patternこのパターンの完全な説明はここにあります)。

この設計では、複数のビルダーを作成する必要がないように、実行するパスを設計する可能性を提供します。

概念は単純です:

  1. 各メソッドが次に何を表示できるかを知っている内部クラスまたはインターフェースに作成ステップを記述します。
  2. すべてのステップインターフェイスを内部静的クラスに実装します。
  3. 最後のステップはBuildStepで、ビルドする必要のあるオブジェクトの作成を担当します。
于 2012-11-25T11:38:03.087 に答える
5

ビルダーパターンは確かに任意です。過度に複雑な場合は過度に複雑です。ファクトリパターンのように、オブジェクトを作成する別の方法を検討することをお勧めします。ビルダーパターンが優れているシナリオはいくつかあると思います。

これは、自動車メーカーを実装する方法の一例です。

public class Car {
    private final boolean hasSunroof;
    private final Color color;
    private final int horsePower;
    private final String modelName;

    private Car(Color color, int horsePower, String modelName, boolean hasSunroof) {
        this.color = color;
        this.horsePower = horsePower;
        this.hasSunroof = hasSunroof;
        this.modelName = modelName;
    }

    public static Builder builder(Color color, int horsePower) {
        return new Builder(color, horsePower);
    }

    public static class Builder {
        private final Color color;
        private final int horsePower;
        private boolean hasSunroof;
        private String modelName = "unknown";

        public Builder(Color color, int horsePower) {
            this.color = color;
            this.horsePower = horsePower;
        }

        public Builder withSunroof() {
            hasSunroof = true;
            return this;
        }

        public Builder modelName(String modelName) {
            this.modelName = modelName;
            return this;
        }

        public Car createCar() {
            return new Car(color, horsePower, modelName, hasSunroof);
        }
    }
}

Builderはネストされたクラスである必要はありませんが、APIを悪用する可能性のある人々からコンストラクターを隠すことができます。また、ビルダーを作成するためにも、最低限必要なパラメーターを指定する必要があることに注意してください。このビルダーは次のように使用できます。

Car car = Car.builder(Color.WHITE, 500).withSunroof().modelName("Mustang").createCar();
于 2011-01-19T17:04:45.340 に答える
2

通常(特にJavaで)表示されるBuilderパターンは、特定のオブジェクトに対する単一のBuilderであり、さまざまなパラメーターを設定するための流動的なインターフェースを備えています。これはEffectiveJavaで提唱されているパターンであり、それが一般的にJavaで見られる理由です。

もちろん、非常に異なる構築シナリオがある場合は、異なるビルダーオブジェクトが理にかなっているかもしれませんが、ここで一歩後退します。1つのオブジェクトに非常に多くの異なるプロパティがある場合、オブジェクトの実行が多すぎる可能性があります。問題の兆候は、ビルダーの複雑さです。

もちろん、現実世界のオブジェクトは複雑ですが、オブジェクト指向設計の基本的な理論は、複雑さが抽象化で階層化されている場合、一度に5〜7個のプロパティを処理する任意のレイヤーで、問題が発生するのを制限できるというものです。複雑すぎて、特定のレイヤーで理解できません。

抽象化レイヤーを適切に設計することの難しさは、上記を現実と同じくらい理想主義にしますが、オブジェクトにやりすぎをさせることのポイントは立っていると思います。

あなたの車の例では、車には多くの層がありますが、それを管理しやすくするための秘訣は、さまざまなアセンブリを区別し、より大きな車をいくつかのアセンブリオプションで構築し、それ自体がいくつかのアセンブリオプションで構築することです。各アセンブリは、独自のオブジェクト、場合によっては独自のビルダーに値します。

于 2011-01-19T17:02:47.690 に答える
2

あなたがあまりにも多くのビルダーを使用していて、各ビルダーが十分に機能していないように私には思えます。クラスごとに1つのビルダーが必要です。フィールド値のセットごとに新しいビルダーを作成しようとしているようです。代わりに、各フィールドには、単一のビルダー内に1つまたは2つのメソッドが必要です。ビルダーの呼び出しは、次のようになります。

Car c = new SUVBuilder().withSunroof().withColor("Red").build();

上記は、SUVが自動車のサブクラスであることを前提としています。そうでない場合は、追加機能でSUVを指定することができます。

于 2011-01-19T17:04:08.733 に答える
0

ビルダーを使用すると、複雑な一連の選択肢を単純なアルゴリズムにカプセル化できます。たとえば、AssemblyLineが車を製造している場合、次のようになります。

buildChassis();
buildDriveTrain();
buildBody();
assemble();
paint();

シャーシ、ドライブトレイン、ボディごとに別々のコンクリートビルダーが必要な場合もありますが、ペイント用に1つだけで済ませることができます。つまり、c'torで色をパラメーター化するだけです。ディレクタークラスはビルダーの詳細を知っているので、適切なコンクリートビルダーをインスタンス化します。組立ラインのクライアントは、手順を順番に実行するだけです。基本的ではない詳細については、コンクリートビルダーをパラメーター化できます(基本的なのは判断の呼び出しです)。

于 2011-01-19T17:00:19.063 に答える