我正在使用builder pattern,将重复的代码提取到'帮助'类中,但重复代码的一个方面我仍然不满意。
构建器模式允许用户链接实现代码:
Car car = new CarBuilder().Wheels(4).Convertible().Build();
每个方法CarBuilder
,Wheels
和Convertible
都返回构建器类(return this
)的相同实例,而Build
方法返回新的 - 实例化Car
。
这是我对通用构建器类的尝试:
public class Builder<T> where T : class
{
private Func<T, T> func;
protected void SetInstantiator(Func<T, T> f) => this.func = f;
protected void Chain(Action<T> action)
{
this.ChainFunc(action);
}
private ChainFunc(Action<T> action)
{
// SNIPPED
}
protected T Instantiate() => this.func(null);
}
这是我的通用构建器的实现:
public class CarBuilder : Builder<Car>
{
public CarBuilder()
{
this.SetInstantiator(c => new Car());
return this;
}
public CarBuilder Wheels(int wheels)
{
this.Chain(c => c.SetWheelCount(wheels));
return this;
}
public CarBuilder Convertible()
{
this.Chain(c => c.RetractableRoof = true);
return this;
}
public Car Build() => this.Instantiate();
}
困扰我的是每次调用return this
方法后重复Chain
并认为我可以将其推入Chain
方法本身,即我想编写如下代码:
public CarBuilder Wheels(int wheels) =>
this.Chain(c => c.SetWheelCount(wheels));
在构建器类中,我尝试将返回类型从void
更改为Builder
:
protected Builder Chain(Action<T> action)
{
this.ChainFunc(action);
return this;
}
...但编译器说返回类型必须是Builder<T>
,即
protected Builder<T> Chain(Action<T> action)
{
this.ChainFunc(action);
return this;
}
好的,公平的,但在我的实现课中,我现在必须做一个演员:
public CarBuilder Wheels(int wheels) =>
(CarBuilder)this.Chain(c => c.SetWheelCount(wheels));
所以我再次重复代码,所有方法现在都必须包含一个强制转换。将类类型从子类型传递给超类型感觉不对。
我想我可能会遗漏一些基本的东西。我可以避免重复演员并且必须从每个构建器实现方法中“返回”吗?
答案 0 :(得分:1)
不要将Chain
放在基类中。相反,将其作为通用扩展方法:
public static TBuilder Chain<TBuilder, TObject>(this TBuilder @this, Action<TObject> a)
where TBuilder: Builder<TObject>
=> ...