如何在.net中实现和扩展Joshua的构建器模式?

gk.*_*gk. 18 .net c#

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

    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() { }
    }
Run Code Online (Sandbox Code Playgroud)
  • 我们如何扩展这样的课程?我们是否需要为每个派生类编写单独的构建器类?

    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) { }
    }
    
    Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 23

在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;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这与EJ2中的模式不完全相同,但是:

  • 在构建时不需要复制数据.换句话说,当你设置属性时,你就是在真实对象上这样做了 - 你还是看不到它.这类似于什么StringBuilder.
  • 在致电Build()保证不变性后,构建器变为无效.遗憾的是,它不能像EJ2版本那样用作一种"原型".
  • 在大多数情况下,我们使用属性而不是getter和setter - 这与C#3的对象初始化器非常吻合.
  • 我们还提供this了为了预C#3用户而返回的setter .

我还没有真正研究过构建模式的继承 - 无论如何它都不支持Protocol Buffers.我怀疑这很棘手.


ala*_*irg 5

这篇博客文章可能会引起您的兴趣

C# 中该模式的一个巧妙变体是使用隐式转换运算符来使对 Build() 的最终调用变得不必要:

public class CustomerBuilder
{

   ......     

   public static implicit operator Customer( CustomerBuilder builder ) 
   {  
      return builder.Build();
   } 
}
Run Code Online (Sandbox Code Playgroud)