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...()

そして、AsServiceProduct() などの代わりに AsPackagedProduct() を呼び出した PackagedProduct です。

これに関するベスト プラクティスを示すサンプルは見つかりませんでした。最終ビルドが同じ型を返すサンプルのみ。

助言がありますか?

4

2 に答える 2

3

ここには 2 つの選択肢があります。

固定されていて、拡張するように設計されていない有限数の製品がある場合は、製品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 に答える