2 votes

Interface fluide pour la construction de différents types de béton

J'ai besoin de suggestions sur la façon de construire une interface fluide agissant comme un constructeur, responsable du retour de différents types concrets en fonction des méthodes appelées.

Imaginons que je doive créer l'un des types suivants à l'aide de mon ProductBuilder (de manière fluide) : Product, ServiceProduct, PackagedProduct (tous deux dérivés de Product).

Je pense utiliser une syntaxe fluide comme celle-ci (d'autres suggestions sont les bienvenues) :

Pour créer un produit :

var product = new ProductBuilder()
   .Create("Simple product")
   .WithPrice(12.5)

Pour créer un ServiceProduct

var product = new ProductBuilder()
   .Create("Service product")
   .WithPrice(12.5)
   .AsServiceProduct()
       .ServiceProductSpecificMethods...()

Et PackagedProduct avec un appel à AsPackagedProduct() au lieu de AsServiceProduct(), etc. Vous voyez ce que je veux dire.

Je n'ai pas trouvé d'exemple de bonnes pratiques en la matière. Il n'y a que des exemples où la version finale renvoie le même type.

Des suggestions ?

3voto

Servy Points 93720

Je vois ici deux options.

S'il y a un nombre limité de produits qui sont fixes et ne sont pas conçus pour être étendus, il suffit de créer une rubrique Create pour chaque produit :

var product = new ProductBuilder()
   .CreateSimple()
   .WithPrice(12.5);

var product = new ProductBuilder()
   .CreateService()
   .WithPrice(12.5)
   .ServiceProductSpecificMethods...();

Si vous ne voulez pas (ou ne pouvez pas avoir) ProductBuilder de connaître tous les types de produits, j'utiliserais des génériques :

public class Product {}
public class SimpleProduct : Product {}
public class ServiceProduct : Product {}

var product = new ProductBuilder<SimpleProduct>()
   .WithPrice(12.5);

Voici un point de départ pour la conception à suivre :

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;
    }
}

1voto

petro.sidlovskyy Points 2871

Si j'ai bien compris, j'utiliserais ici les génériques afin de pouvoir écrire quelque chose comme :

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

Vous pouvez également ajouter la méthode Build avant d'appeler des méthodes de service spécifiques afin de créer le produit final :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X