我需要一些关于如何构建一个充当Builder的流畅界面的建议,负责根据所调用的方法返回不同的具体类型。
想象一下,我需要使用我的ProductBuilder(流利地)创建以下类型之一:Product,ServiceProduct,PackagedProduct(均源自Product)。
我正在考虑使用这样的流利语法(其他建议非常受欢迎):
创建产品:
var product = new ProductBuilder()
.Create("Simple product")
.WithPrice(12.5)
创建ServiceProduct
var product = new ProductBuilder()
.Create("Service product")
.WithPrice(12.5)
.AsServiceProduct()
.ServiceProductSpecificMethods...()
PackagedProduct调用AsPackagedProduct()而不是AsServiceProduct()等。你明白了。
我没有找到显示最佳实践的示例。只有最终构建返回相同类型的样本。
有什么建议吗?
答案 0 :(得分:3)
我在这里看到两个选项。
如果有一定数量的产品已修复且未设计为可扩展,那么只需为每种产品创建Create
方法:
var product = new ProductBuilder()
.CreateSimple()
.WithPrice(12.5);
var product = new ProductBuilder()
.CreateService()
.WithPrice(12.5)
.ServiceProductSpecificMethods...();
如果您不想(或不能)ProductBuilder
知道所有类型的产品,那么我会使用泛型:
public class Product {}
public class SimpleProduct : Product {}
public class ServiceProduct : Product {}
var product = new ProductBuilder<SimpleProduct>()
.WithPrice(12.5);
以下是设计的起点:
public class Product
{
public decimal Price { get; set; }
}
public class SimpleProduct : Product { }
public class ServiceProduct : Product
{
public string Service { get; set; }
}
public class ProductBuilder<T> where T : Product, new()
{
private List<Action<T>> actions = new List<Action<T>>();
public T Build()
{
T product = new T();
foreach (var action in actions)
{
action(product);
}
return product;
}
public void Configure(Action<T> action)
{
actions.Add(action);
}
}
public static class ProductExtensions
{
public static ProductBuilder<T> WithPrice<T>(this ProductBuilder<T> builder, decimal price)
where T : Product
{
builder.Configure(product => product.Price = price);
return builder;
}
public static ProductBuilder<T> WithService<T>(this ProductBuilder<T> builder, string service)
where T : ServiceProduct
{
builder.Configure(product => product.Service = service);
return builder;
}
}
答案 1 :(得分:1)
如果我找对你,我会在这里使用泛型,所以我可以写一些像:
var product = new ProductBuilder()
.Create<Serviceproduct>()
.WithPrice(12.5)
.ServiceProductSpecificMethods...()
您也可以在调用特定服务方法之前添加Build方法,以便实际创建最终产品:
var product = new ProductBuilder()
.Create<Serviceproduct>()
.WithPrice(12.5)
.Build()
.ServiceProductSpecificMethods...()