2010-07-23 12 views
3

La syntaxe ne vous dérange pas. J'ai pensé rendre le poste aussi bref que possible.Hiérarchie des classes

Nous avons une hiérarchie de classes comme ci-dessous.

// abstract class. 
class BaseProd 
// concrete classes. 
class Prod1 : public BaseProd 
class Prod2 : public BaseProd 
class Prod3 : public BaseProd 

Chaque classe dispose de 3 sous-classes comme, Prod1New, Prod1Cancel et Prod1Modify le même cas pour les 2 autres classes. Maintenant, puisque Nouveau, Annuler et Modifier sont les événements, nous pouvons les représenter en utilisant enum. Le problème est, chaque classe a beaucoup de méthodes qui sont très spécifiques à chaque événement. Par exemple.

getRec(); // has specific implementations for each event. 

Supposons qu'il y ait quelque chose comme une méthode de processus.

void Prod1::process() 
{ 
    getRec(); // Each derived class overrides the method. 
    getPayment();// Each derived class overrides the method. 
} 

De cette façon, nous avons 13 classes pour 3 produits ayant chacun 3 événements.
Si nous avons 2 autres produits, les classes augmenteraient de 8.

Peut-on avoir une autre approche de cette hiérarchie?

MISE À JOUR: La suggestion faite par Tyler ne fonctionne que lorsque NewEvent de Prod1 et NewEvent de Prod2 ont la même implémentation. Droite? Mais dans ce cas, ce n'est pas le cas. Au moins pour certaines méthodes, ce n'est pas le cas.

+0

Oui .... vous devriez certainement adopter une approche différente. Pourquoi avez-vous besoin d'une classe différente pour chaque produit? Sont-ils significativement différents (possèdent des propriétés/méthodes différentes) ou ont-ils seulement des valeurs différentes (comme le nom et le prix)? Pourquoi avez-vous besoin de "Modifier" et de "nouvelles" classes pour chaque produit? Tu ne peux pas faire ces choses dans la classe? – mpen

Répondre

3

Je ne vois pas pourquoi les messages Nouveau, Annuler et Modifier devraient être des sous-classes des produits auxquels ils s'appliquent. Cela ne satisfait pas la relation "est-un" qui devrait définir l'héritage. Si la classe D hérite de la classe B, l'instruction "Chaque D est un B" doit être logique et toujours vraie. "Un Prod1 est un BaseProd" (c'est-à-dire "Chaque produit spécifique est un produit") - cela est vrai et logique.

Mais dans le cas des événements, un Prod1Cancel est pas un Prod1. Cela n'a pas de sens de dire "Chaque événement d'annulation de produit1 est un produit1". Au contraire, un Prod1Cancel est un événement relatif àProd1, donc il est plus logique que la classe Prod1Cancel doit contenir un objet Prod1, plutôt que d'hériter de lui.

Étant donné que tous vos produits héritent d'une classe BaseProd, vous devriez vraiment besoin d'une classe pour chaque événement, et non une classe par événement par type de produit, si vous définissez vos classes d'événements comme celui-ci:

class NewProductEvent { 

    public: 

    explicit NewProductEvent(BaseProd* product) 
     : m_product(product) 
    { /* ... */ } 

    void getRec() { /* ... */ } 
    void getPayment() { /* ... */ } 

    private: 

    BaseProd* m_product; // Use this to access the data that the event 
          // needs from the product 
}; 

Ensuite, à l'intérieur de votre méthode Prod1::process(), vous pouvez générer un événement NewProductEvent pour l'objet en cours et appeler les méthodes appropriées à ce sujet:

void Prod1::process() 
{ 
    NewProductEvent event(this); 

    event.getRec(); 
    event.getPayment(); 
} 
+0

Cela fonctionne lorsque NewEvent de Prod1 et NewEvent de Prod2 ont la même implémentation. Droite? Mais dans ce cas, ce n'est pas le cas. Au moins pour certaines méthodes, ce n'est pas le cas. – Jagannath

+0

Ensuite, vous pourriez mettre la fonctionnalité qui diffère entre les produits dans des méthodes virtuelles dans 'BaseProd' qui sont remplacées et implémentées par les différentes classes de produits, et appeler ces méthodes à partir de la classe d'événements. par exemple. Si chaque produit a un moyen différent de calculer son prix, alors vous pourriez avoir une méthode virtuelle 'getPrice()' dans 'ProdBase' et ensuite la classe d'événement pourrait invoquer' m_product-> getPrice() 'pour utiliser l'implémentation spécifique au produit . –

2

Jetez un oeil à la Strategy Pattern. Créez une classe de stratégie pour chaque événement et injectez-la dans la classe Prod lors de l'exécution.

class BaseProd 
{ 
    public BaseProd(EventStrategy event) : _event(event); 
    private EventStrategy _event; 

    virtual public void Process(); 
} 

void Prod1::process() 
{ 
    _event.getRec(); // Each derived class overrides the method. 
    _event.getPayment();// Each derived class overrides the method.  
} 

Maintenant, vous pouvez sous-classe EventStrategy et getRec l'emportait sur(), getPayment(), etc.Et bien sûr, surcharger processus() aussi.

+0

+1 Bonne suggestion! Cela ressemble à l'inversion de ma réponse, créant une classe pour chaque produit-événement et ensuite une seule classe pour tous les produits. Ce serait la meilleure idée si le programme du PO était axé sur la gestion et le traitement * des événements *, tandis que le mien aurait plus de sens si le programme était axé sur la gestion et le traitement * des produits *. On ne sait pas lequel de ces cas est, de la question. –

+0

@Tyler: Il est axé sur la gestion et le traitement des produits. C'est la raison pour laquelle j'ai choisi le vôtre. – Jagannath

Questions connexes