2014-07-07 3 views
0

J'ai une paire existante de types d'objets de gestion, Product et PurchasedProduct, cette dernière étant une sous-classe de la première. Le premier représente un objet dans le panier du client, toutes les informations (sauf la quantité) étant lues à partir d'un produit "archétypal" stocké dans la base de données. Lorsqu'un client effectue un retrait, le contenu du panier est stocké dans la base de données avec l'ID de son archétype, mais avec toutes les informations d'achat potentiellement variables (prix net, taux de TVA, quantité, etc.) "cuites "dans le dossier. C'est ainsi que lorsqu'un client vérifie l'historique de sa commande, chaque commande crée un objet PurchasedProduct qui rapporte les valeurs au moment de la sortie, plutôt que les valeurs archétypales. Ainsi, lors de la récupération d'une instance de produit achetée, l'archétype peut être lu en premier pour remplir la majorité des données (car PurchasedProduct est-Product), puis l'instance achetée est lue pour remplir les valeurs au moment du paiement. .Structure des classes Product, ProductBundle et "Purchased"

Maintenant, le client souhaite avoir des «paquets» de produits. Ceux-ci agissent de toutes les manières identiquement à un «produit» singulier, excepté le suivant:

1) Un paquet contient une liste de Product objets (avec des quantités fixes), mais aura son propre prix sans rapport avec les produits contenus, son propre quantité, etc. 2) à l'achat, non seulement besoin d'enregistrer son propre prix, etc., mais temps de paiement qui de ses produits constitutifs

Ma pensée initiale était d'avoir:

ProductBundle : Product 
{ 
    public List<Product> Products { get; set; } 
    // other stuff as needed 
} 

PurchasedProductBundle : PurchasedProduct 
{ 
    public List<PurchasedProduct> Products { get; set; } 
    // other stuff as needed 
} 

Cela semblerait ajouter beaucoup de complexité à la ProductRepository dont responsi bility convertit principalement les ID de produit en objets métier. Il aurait besoin de vérifier les données entrantes et de basculer entre plusieurs chemins pour chacun de ces quatre types, où certains chemins ont des fonctionnalités en double. Il semble également dupliquer la propriété list-of-sub-products. Enfin, un PurchasedProductBundle est à la fois un ProductBundle et un PurchasedProduct, mais C# n'a pas d'héritage multiple, bien sûr.

Une autre voie pourrait être la composition, donc un ProductBundle est une composition d'un seul Product et une liste de Product s, mais cela semble comme beaucoup de passe-partout pour passer accès à la propriété par le Product sous-jacente.

Est-ce que l'un ou l'autre est un itinéraire judicieux, ou y at-il un motif vraiment net qui me manque?

Répondre

1

Une possibilité est de considérer qu'un PurchasedProduct ne doit pas être "dérivé d'un Product". Mais plutôt avoir l'interface IProduct, qui est soit un PurchasedProduct ou Product. Vos offres groupées sont les suivantes: IProductBundle (IProduct) et IEnumerable<IProduct> Products { get; set; }, pour PurchasedProductBundle et ProductBundle.

La raison derrière c'est qu'un PurchasedProduct est pas un Product, il est beaucoup plus un Achat ou OrderLine qu'un Product, et de nombreuses raisons peuvent demander de changer le prix, non seulement le fait que les prix évolueront avec le temps, il pourrait y avoir une offre commerciale, un coupon.

Une autre possibilité est de considérer que cela ne vous dérange pas du tout quels sont les prix des produits inclus dans un paquet? Après tout, vous allez probablement annoncer le pourcentage de rabais globalement, mais c'est une autre question.

+0

Merci! J'aime les suggestions 'IProduct' et' IProductBundle' et le raisonnement sur 'PurchasedProduct' n'est pas vraiment un' Product', mais il y a beaucoup de fonctionnalités partagées entre 'Product' et' ProductBundle', avec seulement 'IEnumerable La propriété basée sur 'est différente. Donc je pense que cette partie de l'héritage est correcte, et je devrais revenir aux types 'Purchased' et les restructurer. –