是否可以编写遵循给定语法的TestDataBuilder?

因此,例如:



我知道如何为汽车编写基本的构建器,这不是问题。

但是如何才能实现只能将新窗户添加到门上呢?

因此,这是允许的:

var car = CarBuilderWithSyntax.Create()
              .WithDoor()
                  .HavingSide(Sides.Left)
                  .WithWindow()
                      .HavingWidth(50)
                      .HavingHeight(50)
            .Build();


但这是不允许的:

var car = CarBuilderWithSyntax.Create()
              .WithWindow()
                  .HavingWidth(50)
                  .HavingHeight(50)
          .Build();


是否有可能执行此语法规则?

可以通过使用继承自汽车制造商的其他车门制造商来实现吗?

汽车制造商是否应实现IDoorBuilderWithSyntax之类的不同接口,它们定义方法ICarBuilderWithSyntax WithWindow()ICarBuilderWithSyntax HavingSide(); ICarBuilderWithSyntax HavingColor()

最佳答案

您可以执行以下操作:

public enum Sides
{
    Left,
}

public class Car
{

}

public class CarBuilderWithSyntax
{
    protected CarBuilderWithSyntax ParentBuilder { get; private set; }

    public static CarBuilderWithSyntax Create()
    {
        return new CarBuilderWithSyntax(null);
    }

    protected CarBuilderWithSyntax(CarBuilderWithSyntax parent)
    {
        ParentBuilder = parent;
    }

    protected CarBuilderWithSyntax GetParentBuilder()
    {
        CarBuilderWithSyntax parentBuilder = this;

        while (parentBuilder.ParentBuilder != null)
        {
            parentBuilder = parentBuilder.ParentBuilder;
        }

        return parentBuilder;
    }

    public DoorBuilder WithDoor()
    {
        return new DoorBuilder(GetParentBuilder());
    }

    public CarBuilderWithSyntax WithEngine(int cmq)
    {
        if (ParentBuilder != null)
        {
            return GetParentBuilder().WithEngine(cmq);
        }

        // Save somewhere this information
        return this;
    }

    public Car Build()
    {
        return null;
    }

    public class DoorBuilder : CarBuilderWithSyntax
    {
        public DoorBuilder(CarBuilderWithSyntax builder)
            : base(builder)
        {
        }

        protected new DoorBuilder GetParentBuilder()
        {
            DoorBuilder parentBuilder = this;

            while ((parentBuilder.ParentBuilder as DoorBuilder) != null)
            {
                parentBuilder = parentBuilder.ParentBuilder as DoorBuilder;
            }

            return parentBuilder;
        }

        public DoorBuilder HavingSide(Sides side)
        {
            // Save side this information somewhere
            return GetParentBuilder();
        }

        public WindowBuilder WithWindow()
        {
            return new WindowBuilder(this);
        }

        public class WindowBuilder : DoorBuilder
        {
            public WindowBuilder(DoorBuilder builder)
                : base(builder)
            {
            }

            public WindowBuilder HavingWidth(int width)
            {
                // Terminal elements don't need to do the GetParentBuilder()
                return this;
            }

            public WindowBuilder HavingHeight(int width)
            {
                // Terminal elements don't need to do the GetParentBuilder()
                return this;
            }
        }
    }
}


现在,您只需要选择保存Builder信息的方式/位置...,请注意各种类如何互连以及各种GetParentBuilder()的用法。

var car = CarBuilderWithSyntax.Create()
  .WithDoor()
      .HavingSide(Sides.Left)
      .WithWindow()
          .HavingWidth(50)
          .HavingHeight(50)
  .WithEngine(100)
  .Build();

07-27 23:07