与嵌套对象的生成器模式

时间:2016-07-20 11:45:32

标签: c# design-patterns fluent method-chaining builder-pattern

嗨,我遇到了问题。

我想实现构建器模式,以便更轻松地创建对象。我面临的问题与嵌套对象有关。我想要创建的对象中包含其他对象的列表,而且我对如何解决它没有任何想法。

我希望能够执行以下操作(例如,更简单的对象):

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

或类似的东西:

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

示例应该代表我的情况,尽管如果有多种类型的嵌套对象。

1 个答案:

答案 0 :(得分:12)

给出这样的代码

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

您的构建器非常简单,在AddItem构建器方法中使用了一些简单谓词,以允许使用者在类似的构建器中配置每个项目"模式到顶级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;
    }
}

工作示例:http://rextester.com/IRR50897