6

ビルダーパターンを学んでいます

上記のリンク (Java の例) で、Builder が複数のコンポーネントを構築するためのインターフェースを提供していることに気付きました。それらを呼び出すとともに、getProduct() も呼び出します。

私が理解できない点は、Director がこれらのすべてのコンポーネント構成メソッドを 1 つずつ呼び出して、最終的に結果を取得する必要があるのはなぜかということです。

     /** "Director" */
 class Waiter {
    private PizzaBuilder pizzaBuilder;


public void setPizzaBuilder(PizzaBuilder pb) { pizzaBuilder = pb; }
public Pizza getPizza() { return pizzaBuilder.getPizza(); }

public void constructPizza() {
   pizzaBuilder.createNewPizzaProduct(); 
   pizzaBuilder.buildDough(); // construct component 1
   pizzaBuilder.buildSauce(); // construct component 2
   pizzaBuilder.buildTopping();  // construct component 3
}

}

コンポーネント 1、2、3 を構築するためのコードを、Director ではなく ConcreteBuilder クラス自体に含めて、実際に Director レイヤーを削除してみませんか。

上記のアプローチがビルダーのパターンを別のものに変える可能性があることは理解していますが、ディレクターが段階的に仕事をしている理由がわかりません。メリットは何ですか?取締役が複数いるとコードが重複しますよね?Builder パターンの実行の背後にある動機を理解していない可能性があります...

UPDATE : Builder パターンは、より大きな複雑なオブジェクトを作成しながら、カスタマイズ可能なコンポーネントの選択を提供することに重点を置いていますか? そうでなければ、のところ、追加のレイヤーであるディレクターを導入する意味がわかりません。

その場合でも、Decorator パターンは、コンポーネントを動的にカスタマイズすることで同じことを達成するためのより良いアイデアかもしれません。どこかでビルダーの背後にあるポイントが欠けています.. :(

4

4 に答える 4

8

Director クラスの目的は、オブジェクトを作成するためのアルゴリズムをカプセル化することです。つまり、オブジェクトを実際に構成する部分のコードから構築ロジックのコードを分離します。Director クラスがないと、Builder クラスはより大きくなり、モジュール性が低下するため、保守が難しくなり、再利用性が低下します。

あなたが参照しているウィキペディアの例はかなり単純化されています。複雑なオブジェクトの場合、構築メカニズムは通常より複雑になり、Director は必ずしも Builder メソッドを定義された順序で 1 つずつ呼び出すとは限りません。たとえば、クラスCakeを考えてみましょう。Builder は、これら 3 つの部分をこの特定の順序で構築するための 3 つのメソッドを定義しますが、Director クラスのメソッドは次のようになります。ChocolateLayerCreamLayerStrawberryconstructCake()

public void constructCake() {
   CakeBuilder.createNewCakeProduct(); 
   CakeBuilder.buildChocolateLayer(); 
   CakeBuilder.buildCreamLayer(); 
   CakeBuilder.buildChocolateLayer(); // 2nd call of the same Builder method
   int totalStrawberries = 3 + new Random().nextInt(2);
   for (int i = 1; i <= totalStrawberries; i++) 
      CakeBuilder.buildStrawberry(); // put some strawberries on top
   // Please don't try this recipe at home! 
}

Builder と Decorator の違いについては、Builder Vs Decorator パターンの質問を確認してください。

于 2013-03-09T20:56:03.053 に答える
7

オブジェクトを構築するのは Director ではなく Builder であり、それは Product と呼ばれます。Director が存在する理由の 1 つは、クラスのユーザーがオブジェクトの構築に必要な手順について何も知らないためです。すべてを 1 つの方法に単純化するというこのすべての話は、自動車を一輪車にできない理由を尋ねるようなものです。私たちはできました。それはもはや車ではなく、b. 一輪車ではできないことを車でできるわけではありません。

Builder を見る最良の方法の 1 つは、テンプレート メソッドとファクトリの融合です。さまざまな製品の作成をサポートできるように、抽象的な構築プロセスが必要ですが、構築プロセスには多くの手順が含まれます。Director/Builder アーキテクチャが整ったら、新しい具体的な実装を提供することで、新しい Builder を簡単に追加できるという考え方です。Builder は同様に構築セマンティクスの詳細を無視し、構築の必要な各部分の実装を提供するだけなので、テンプレート メソッドに似ています (また、一部のロジックは Builder 階層の抽象ベースになり、量をさらに拡大する可能性があることにも注意してください)。後のエクステンダーが無料で取得する自動機能の)。

于 2013-03-09T23:41:31.687 に答える
5

Builder パターンを誤解していると思います。あなたは、さまざまなコンポーネントを構築するプロセスを 1 つのメソッドにマージできると言っていますが、それは本当ですが、このオブジェクト作成設計パターンの鍵ではありません。このコードをもう一度見てください。

class Waiter {
    private PizzaBuilder pizzaBuilder;

    public void setPizzaBuilder(PizzaBuilder pb) { pizzaBuilder = pb; }
    public Pizza getPizza() { return pizzaBuilder.getPizza(); }

    public void constructPizza() {
        pizzaBuilder.createNewPizzaProduct();
        pizzaBuilder.buildDough();
        pizzaBuilder.buildSauce();
        pizzaBuilder.buildTopping();
    }
}

Waiterは a でのみ機能することに注意してください。彼はそれが aか a かPizzaBuilderを知りません。それがこのパターンの目標です。この他のコードでは:SpicyPizzaBuilderHawaiianPizzaBuilder

class BuilderExample {
    public static void main(String[] args) {
        Waiter waiter = new Waiter();
        PizzaBuilder hawaiianPizzaBuilder = new HawaiianPizzaBuilder();
        PizzaBuilder spicyPizzaBuilder = new SpicyPizzaBuilder();

        waiter.setPizzaBuilder( hawaiianPizzaBuilder );
        waiter.constructPizza();

        Pizza pizza = waiter.getPizza();

        waiter.setPizzaBuilder( spicyPizzaBuilder );
        waiter.constructPizza();

        Pizza anotherPizza = waiter.getPizza();
    }
}

これがどのように機能するかを実際に見ることができます。AWaiterが作成され、最初に a が渡されHawaiianPizzaBuilder、次に aが渡されSpicyPizzaBuilderます。同じインスタンスのWaiteryou を使用して、ピザを作成して要求すると、正しいピザが届けられます。私が自分自身を説明し、このコメントがお役に立てば幸いです ;) 頑張ってください!!!

于 2013-03-09T06:11:50.923 に答える
2

ビルダー パターンの説明: オブジェクト (製品) があり、オブジェクトの構築には多くのパラメーターまたはコンポーネント (他のオブジェクト) が必要であると仮定しましょう。異なるパラメーターを持つ多くのコンストラクターを作成するか、唯一のコンストラクター内に多くの論理ステートメントを導入してこれを選択し、そのオブジェクトを拒否し、さらに悪いことに、これらのコンポーネントを順番に (特定の順序で) 構築する必要がある可能性があります。それらに対していくつかのビジネスルールチェックを行います。これが要約すると、パラメーター (コンポーネント) に密接に結合され、保守が困難な複雑なコンストラクターになります。解決策は、このロジックを具体的なビルダーに移動して、呼び出してオブジェクトを取得することですConcreteBuilder.BuildComponent1(), ConcreteBuilder.BuildComponent2(), ..., ConcreteBuilder.GetMeMyObject()しかし、これにより、クライアント コードが構築プロセスに密接に結び付けられます。各クライアントは、最愛のオブジェクトを構築するために必要なすべてのステップを完全に認識しているため、構築プロセスに何らかの変更が加えられると、あちこちのクライアント コードをすべて変更する必要があります。 、これを解決するために、Builder パターンは、これらのステップをカプセル化するDirectorを導入し、すべてのクライアントがDirectorで Build() メソッドを呼び出してオブジェクトを構築します。要約すると、Director が存在するため、クライアント コードは最愛のオブジェクトを作成するために必要な手順を認識したり、密接に結合したりしません。BuildComponent1(), BuildComponent2()メソッドが存在するのは、ビルダー パターンが存在する問題を解決するためであり、冒頭で述べた問題を解決するためでもあります。コンポーネントの構築プロセスに順序を適用できるようになりました。各コンクリートに固有のビジネス ロジックを適用することもできます。最終的なオブジェクト (製品) はそのコンポーネントを必要とせず、この複雑な構築プロセスを自分の仕事をする最愛のオブジェクトから離れてカプセル化したため、特定の具体的なビルダーの実装を空のままにすることも選択できます。自分で構築する方法を気にせずに最適です。

于 2013-03-09T23:30:17.290 に答える