2016-07-20 27 views
6

Cześć Utknąłem z problemem.Wzór konstruktora z obiektami zagnieżdżonymi

Chcę zaimplementować wzór konstruktora, aby ułatwić tworzenie moich obiektów. Problem, który napotykam, ma związek z zagnieżdżonym obiektem. Obiekt, który chciałbym utworzyć, zawiera listę innych obiektów i nie mam pomysłu, jak go rozwiązać.

Chcę być w stanie wykonać następujące (prostsze obiekty przykładowo):

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

albo coś podobnego:

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

przykład powinien być reprezentatywny dla mojej sytuacji, choć jeśli mam więcej niż jeden typ zagnieżdżonego obiektu.

+1

Co aktualny kod 'ReceiptBuilder' wygląd l ike? Jaka jest struktura elementów, które próbujesz dodać za pomocą 'AddItem'? – Jamiec

+0

Czy ogólny trik nie zwraca samej instancji jako wartości zwracanej z tych operacji? Dlaczego więc nie "' ... .AddFoo (new Foo(). WithIngredient ("value"). WithType ("value")). ... ''? Po prostu powtórz wzorzec dla tych podtypów i użyj specjalnych funkcji dodawania/właściwości pod-kolekcji. – BitTickler

+0

Przydałoby się zobaczyć "Pokwitowanie" klasy – konkked

Odpowiedz

6

danego kodu jak ten

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); 

Twój budowniczym jest dość prosta, wykorzystując kilka prostych orzeczników wewnątrz metody AddItem budowniczy, aby umożliwić konsumentowi skonfigurować każdą pozycję w podobnym „budowniczy” wzór na górę poziom ReceiptBuilder:

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; 
    } 
} 

przykład robocza: http://rextester.com/IRR50897