2

我需要一些关于如何构建作为 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() 等。你明白了。

我还没有找到显示这方面最佳实践的示例。只有最终构建返回相同类型的样本。

有什么建议么?

4

2 回答 2

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;
    }
}
于 2012-10-25T18:45:26.473 回答
1

如果我理解正确,我会在这里使用泛型,这样我就可以编写如下内容:

var product = new ProductBuilder()
.Create<Serviceproduct>()
.WithPrice(12.5)
   .ServiceProductSpecificMethods...()

您还可以在调用特定服务方法之前添加 Build 方法,以便它实际创建最终产品:

var product = new ProductBuilder()
.Create<Serviceproduct>()
.WithPrice(12.5)
.Build()
   .ServiceProductSpecificMethods...()
于 2012-10-25T18:38:28.547 回答