c# - 如何在.net中实现和扩展Joshua的 builder 模式?

标签 c# .net

下面是我试过的代码,有没有更好的方法呢?

    public class NutritionFacts
    {
        public static NutritionFacts.Builder Build(string name, int servingSize, int servingsPerContainer)
        {
            return new NutritionFacts.Builder(name, servingSize, servingsPerContainer);
        }

        public sealed class Builder
        {
            public Builder(String name, int servingSize,
            int servingsPerContainer)
            {
            }
            public Builder totalFat(int val) { }
            public Builder saturatedFat(int val) { }
            public Builder transFat(int val) { }
            public Builder cholesterol(int val) { }
            //... 15 more setters
            public NutritionFacts build()
            {
                return new NutritionFacts(this);
            }
        }
        private NutritionFacts(Builder builder) { }
        protected NutritionFacts() { }
    }
  • 我们如何扩展这样的类?做 我们需要编写单独的构建器 每个派生类 上课?

    public class MoreNutritionFacts : NutritionFacts
    {
        public new static MoreNutritionFacts.Builder Build(string name, int servingSize, int servingsPerContainer)
        {
            return new MoreNutritionFacts.Builder(name, servingSize, servingsPerContainer);
        }
        public new sealed class Builder
        {
            public Builder(String name, int servingSize,
            int servingsPerContainer) {}
            public Builder totalFat(int val) { }
            public Builder saturatedFat(int val) { }
            public Builder transFat(int val) { }
            public Builder cholesterol(int val) { }
            //... 15 more setters
            public Builder newProperty(int val) { }
            public MoreNutritionFacts build()
            {
                return new MoreNutritionFacts(this);
            }
        }
        private MoreNutritionFacts(MoreNutritionFacts.Builder builder) { }
    }
    

最佳答案

在 Protocol Buffers 中,我们像这样实现构建器模式(大大简化):

public sealed class SomeMessage
{
  public string Name { get; private set; }
  public int Age { get; private set; }

  // Can only be called in this class and nested types
  private SomeMessage() {}

  public sealed class Builder
  {
    private SomeMessage message = new SomeMessage();

    public string Name
    {
      get { return message.Name; }
      set { message.Name = value; }
    }

    public int Age
    {
      get { return message.Age; }
      set { message.Age = value; }
    }

    public SomeMessage Build()
    {
      // Check for optional fields etc here
      SomeMessage ret = message;
      message = null; // Builder is invalid after this
      return ret;
    }
  }
}

这与 EJ2 中的模式不太一样,但是:

  • 构建时不需要复制数据。换句话说,当您设置属性时,您是在真实对象上这样做——您只是还看不到它。这类似于 StringBuilder 的作用。
  • 构建器在调用Build() 后失效以保证不变性。不幸的是,这意味着它不能像 EJ2 版本那样用作一种“原型(prototype)”。
  • 在大多数情况下,我们使用属性而不是 getter 和 setter - 这非常适合 C# 3 的对象初始值设定项。
  • 为了 C#3 之前的用户,我们还提供返回 this 的 setter。

我还没有真正研究过构建器模式的继承——它在 Protocol Buffers 中是不支持的。我怀疑这很棘手。

关于c# - 如何在.net中实现和扩展Joshua的 builder 模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/313729/

相关文章:

c# - 基于 SSL 客户端证书限制对 Web 服务的访问(授权)

c# - FormsAuthentication.SignOut() 使用 javascript

.net - 如何在 Azure CI/CD 管道中自动执行 mongo DB 脚本

C# WPF 应用程序 .NET Framework 4.8 与 .NET Core 3.1 与 .NET 5.0

C# 使用反射创建 AutoMapper 映射

c# - 通用类/方法的单元测试方法

c# - 防止 "Backspace"键被按下

.net - 在 MAC OS 上安装 WIX 工具集并创建 MSI

c# - 需要高效稳定的 PriorityQueue 实现

c# - .net XML 序列化 - 存储引用而不是对象副本