Jagannath
Jagannath

Reputation: 4025

Class Hierarchy

Please don't mind about the syntax. I thought of making the post as brief as possible.

We have a class hierarchy as below.

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

Each class has 3 sub classes like, Prod1New, Prod1Cancel and Prod1Modify the same case for the other 2 classes. Now, since New, Cancel and Modify are the events, we can represent them using enum.

The problem is, each class has lot of methods that are very specific to each event. Eg.

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

Let's say there is something like process method.

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

This way, we have 13 classes for 3 products having 3 events each.
If we have 2 more products the classes would grow by 8.

Can we have any alternate approach to this hierarchy?

UPDATE: The suggestion made by Tyler works only when Prod1's NewEvent and Prod2's NewEvent have the same implementation. Right? But in this case it is not. Atleast for some of the methods it is not.

Upvotes: 3

Views: 314

Answers (2)

Ozan
Ozan

Reputation: 4415

Take a look at the Strategy Pattern. Make a strategy class for each event and inject it into the Prod class at runtime.

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

Now you can subclass EventStrategy and overrode getRec(), getPayment(), etc. And of course override process() too.

Upvotes: 2

Tyler McHenry
Tyler McHenry

Reputation: 76660

I don't see why the New, Cancel, and Modify messages should be subclasses of the products that they apply to. This doesn't satisfy the "is-a" relationship that should define inheritance. If class D inherits from class B, the statement "Every D is a B" should make sense and always be true. "A Prod1 is a BaseProd" (i.e. "Every specific product is a product") -- that is true and makes sense.

But in the case of events, a Prod1Cancel is not a Prod1. It doesn't make sense to say "Every product1 cancellation event is a product1." Rather, a Prod1Cancel is an event relating to Prod1, so it makes more sense that the Prod1Cancel class should contain a Prod1 object, rather than inheriting from it.

Since all of your products inherit from a BaseProd class, you should really only need one class for each event, and not one class per event per product type, if you define your event classes like this:

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

Then, inside your Prod1::process() method, you could generate a NewProductEvent event for the current object, and call the appropriate methods on it:

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

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

Upvotes: 3

Related Questions