使用语法编写测试数据生成器
Writing a test data builder with syntax
是否可以编写遵循给定语法的 TestDataBuilder?
例如:
我知道如何为汽车编写基本构建器,这不是问题。
但是我怎样才能实现,我只能给门添加新的windows?
所以这是允许的:
var car = CarBuilderWithSyntax.Create()
.WithDoor()
.HavingSide(Sides.Left)
.WithWindow()
.HavingWidth(50)
.HavingHeight(50)
.Build();
但这不允许:
var car = CarBuilderWithSyntax.Create()
.WithWindow()
.HavingWidth(50)
.HavingHeight(50)
.Build();
是否有可能强制执行此语法规则?
这可以通过使用继承汽车制造商的额外门制造商来实现吗?
汽车制造商是否应该实现不同的接口,例如定义方法 ICarBuilderWithSyntax WithWindow()
和 ICarBuilderWithSyntax HavingSide();
ICarBuilderWithSyntax HavingColor()
的 IDoorBuilderWithSyntax?
你可以这样做:
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;
}
}
}
}
现在你只需要选择how/where来保存Builder
的信息...注意各个类是如何互连的,以及各个GetParentBuilder()
是如何使用的.
var car = CarBuilderWithSyntax.Create()
.WithDoor()
.HavingSide(Sides.Left)
.WithWindow()
.HavingWidth(50)
.HavingHeight(50)
.WithEngine(100)
.Build();
是否可以编写遵循给定语法的 TestDataBuilder?
例如:
我知道如何为汽车编写基本构建器,这不是问题。
但是我怎样才能实现,我只能给门添加新的windows?
所以这是允许的:
var car = CarBuilderWithSyntax.Create()
.WithDoor()
.HavingSide(Sides.Left)
.WithWindow()
.HavingWidth(50)
.HavingHeight(50)
.Build();
但这不允许:
var car = CarBuilderWithSyntax.Create()
.WithWindow()
.HavingWidth(50)
.HavingHeight(50)
.Build();
是否有可能强制执行此语法规则?
这可以通过使用继承汽车制造商的额外门制造商来实现吗?
汽车制造商是否应该实现不同的接口,例如定义方法 ICarBuilderWithSyntax WithWindow()
和 ICarBuilderWithSyntax HavingSide();
ICarBuilderWithSyntax HavingColor()
的 IDoorBuilderWithSyntax?
你可以这样做:
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;
}
}
}
}
现在你只需要选择how/where来保存Builder
的信息...注意各个类是如何互连的,以及各个GetParentBuilder()
是如何使用的.
var car = CarBuilderWithSyntax.Create()
.WithDoor()
.HavingSide(Sides.Left)
.WithWindow()
.HavingWidth(50)
.HavingHeight(50)
.WithEngine(100)
.Build();