2016-07-20 18 views
6

Hi Ich stecke mit einem Problem fest.Builder-Muster mit verschachtelten Objekten

Ich möchte das Builder-Muster implementieren, um die Erstellung meiner Objekte zu erleichtern. Das Problem, mit dem ich konfrontiert bin, hat mit verschachtelten Objekten zu tun. Das Objekt, das ich erstellen möchte, enthält eine Liste anderer Objekte, und ich habe keine Ahnung, wie ich es angehen soll.

Ich möchte folgende (Simpler Objekte zum Beispiel) in der Lage sein zu tun:

Receipt RestaurantReceipt = new ReceiptBuilder() 
.withDate("value") 
.withName("value") 
.AddItem("value") 
    .WithIngredients("value") 
    .WithType("value") 
.AddItem("value") 
    .WithIngredients("value") 
    .WithType("value") 
.build(); 

Oder so etwas wie:

Receipt RestaurantReceipt = new ReceiptBuilder() 
.withDate("value") 
.withName("value") 
.AddItem("value", item => { 
    .WithIngredients("value") 
    .WithType("value") 
}) 
.AddItem("value", item => { 
    .WithIngredients("value") 
    .WithType("value") 
}) 
.build(); 

Beispiel für meine Situation repräsentativ sein sollte, aber wenn mehr bekam als eine Art verschachteltes Objekt.

+1

Was für 'ReceiptBuilder' Blick l Ihre aktuellen Code tut Ike? Was ist die Struktur der Elemente, die Sie versuchen, mit 'AddItem' hinzuzufügen? – Jamiec

+0

Ist der allgemeine Trick, die Instanz selbst nicht als Rückgabewert von diesen Operationen zurückzugeben? Warum also nicht '' ... .AddFoo (new Foo(). WithIngredient ("value"). WithType ("value")). ... ''? Wiederholen Sie einfach das Muster für diese Untertypen und verwenden Sie Untersammlungsspezifische Add-Funktionen/Eigenschaften. – BitTickler

+0

Wäre hilfreich, wenn Sie die Klasse "Receipt" sehen würden – konkked

Antwort

6

Da Code wie diese

var rb = new ReceiptBuilder(); 
var receipt = rb.WithName("Name") 
      .WithDate(DateTime.Now) 
      .WithItem("Item1", i => i.WithIngredients("Ingredients1")) 
      .WithItem("Item2", i => i.WithIngredients("Ingredients1")) 
      .Build(); 
Console.WriteLine(receipt); 

ist Ihr Erbauer ziemlich einfach, einige einfachen Prädikate innerhalb des AddItem Builder Verfahrens unter Verwendung der Verbraucher zu konfigurieren, jedes Element in einem ähnlichen „Builder“ Muster an die Spitze zu ermöglichen, ReceiptBuilder Ebene:

public class ReceiptBuilder 
{ 
    private Receipt r; 

    public ReceiptBuilder() 
    { 
     r = new Receipt(); 
    } 

    public ReceiptBuilder WithName(string name) 
    { 
     r.Name = name; 
     return this; 
    } 

    public ReceiptBuilder WithDate(DateTime dt) 
    { 
     r.Date = dt; 
     return this; 
    } 

    public ReceiptBuilder WithItem(string text, Action<ReceiptItemBuilder> itemBuilder) 
    { 
     var rib = new ReceiptItemBuilder(text); 
     itemBuilder(rib); 
     r.AddItem(rib.Build()); 
     return this; 
    } 

    public Receipt Build() 
    { 
     return r; 
    } 
} 

public class ReceiptItemBuilder 
{ 
    private ReceiptItem ri; 

    public ReceiptItemBuilder(string text) 
    { 
     ri = new ReceiptItem(text); 
    } 

    public ReceiptItemBuilder WithIngredients(string ings) 
    { 
     ri.Ingredients = ings; 
     return this; 
    } 

    // WithType omitted for brevity. 

    internal ReceiptItem Build() 
    { 
     return ri; 
    } 
} 

Arbeitsbeispiel: http://rextester.com/IRR50897

Verwandte Themen