【问题标题】:Builder pattern with nested objects具有嵌套对象的构建器模式
【发布时间】:2023-03-20 21:35:01
【问题描述】:

您好,我遇到了一个问题。

我想实现构建器模式以更轻松地创建我的对象。我面临的问题与嵌套对象有关。我想创建的对象中包含其他对象的列表,我真的不知道如何处理它。

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

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

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

【问题讨论】:

  • ReceiptBuilder 的当前代码是什么样的?您尝试使用AddItem 添加的项目的结构是什么?
  • 一般技巧是不将实例本身作为这些操作的返回值返回吗?那么为什么不 `` ... .AddFoo(new Foo().WithIngredient("value").WithType("value"))。 ……``?只需重复这些子类型的模式并使用子集合特定的添加功能/属性。
  • 看看Receipt类会很有帮助
  • 拥有一个额外的 Builder 类有什么好处吗?或者这通常只有在Receipt 对象本身没有实现模式时才这样做?不是构建器,而是扩展方法不是更可取的吗?

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


【解决方案1】:

给定这样的代码

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

您的构建器非常简单,在 WithItem 构建器方法中使用一些简单的谓词,以允许消费者以与顶级 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

【讨论】:

  • 你能解释一下这里发生了什么吗? itemBuilder(rib);
猜你喜欢
  • 1970-01-01
  • 2016-01-17
  • 2017-01-25
  • 1970-01-01
  • 2016-01-05
  • 1970-01-01
  • 2018-07-24
  • 2021-05-24
  • 1970-01-01
相关资源
最近更新 更多