类层次结构

3
请不要在意语法问题。我考虑尽可能简短地发帖。
我们有以下的类层次结构。
```html

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   

每个类都有3个子类,如Prod1New、Prod1Cancel和Prod1Modify,其他2个类也是这样。现在,由于New、Cancel和Modify是事件,我们可以使用枚举来表示它们。
问题是,每个类都有很多方法,这些方法非常特定于每个事件。例如:
getRec(); // has specific implementations for each event.   

假设有一个名为“process method”的东西。
void Prod1::process()
{
   getRec(); // Each derived class overrides the method.   
   getPayment();// Each derived class overrides the method.   
}  

这样,我们有3个产品,每个产品有3个事件,共有13个类。
如果我们再增加2个产品,类的数量会增加8个。

我们能否有任何替代方法来处理这种层次结构?

更新: Tyler提出的建议仅在Prod1的NewEvent和Prod2的NewEvent具有相同实现时才有效。对吧?但是在这种情况下并非如此。至少对于某些方法而言不是这样。


是的...你肯定应该采取不同的方法。为什么你需要为每个产品都创建一个不同的类呢?它们是否有很大的区别(具有不同的属性/方法),还是只有不同的值(如名称和价格)?为什么你需要为每个产品都需要“修改”和“新建”类?难道你不能将这些东西作为类内的方法吗? - mpen
2个回答

3
我不明白为什么新建、取消和修改消息应该是它们所应用的产品的子类。这不符合继承应该定义的"is-a"关系。如果类 D 继承自类 B,那么语句"每个 D 都是一个 B" 应该有意义并且永远成立。"一个 Prod1 是一个 BaseProd"(即 "每个具体的产品都是一个产品") - 这是真实的并且有意义的。
但在事件的情况下,Prod1Cancel 不是一个 Prod1。说"每个产品1的取消事件都是产品1"是没有意义的。相反,Prod1Cancel 是与 Prod1 相关的事件,因此 Prod1Cancel 类应该包含一个 Prod1 对象,而不是从它继承。
由于您的所有产品都继承自 BaseProd 类,如果您像这样定义事件类,则基本上只需要一个类来处理每个事件,而不是每种产品类型的每个事件一个类:
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
};

然后,在您的Prod1::process()方法内,您可以为当前对象生成一个NewProductEvent事件,并调用适当的方法:

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

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

这只有在Prod1的NewEvent和Prod2的NewEvent具有相同的实现时才有效。对吧?但在这种情况下,它并不是这样的。至少对于某些方法来说是不一样的。 - Jagannath
然后,您可以将不同产品之间差异的功能放入“BaseProd”中的虚拟方法中,这些方法由各个产品类覆盖和实现,并从事件类中调用这些方法。例如,如果每个产品都有一种不同的计算价格方式,则可以在ProdBase中拥有一个虚拟的getPrice()方法,然后事件类可以调用m_product->getPrice()以使用特定于产品的实现。 - Tyler McHenry

2

看一下策略模式。为每个事件创建一个策略类,并在运行时将其注入到Prod类中。

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

现在你可以子类化EventStrategy并重写getRec(), getPayment()等方法。当然,也可以重写process()方法。


+1 好建议!这似乎是我的答案的反转,为每个产品事件创建一个类,然后只为所有产品创建一个单独的类。如果OP的程序是围绕管理和处理事件而设计的,则这将是最好的想法,而我的答案则更适合程序围绕管理和处理产品而设计的情况。从问题中并不清楚哪种情况是正确的。 - Tyler McHenry
@Tyler:它的定位是管理和处理产品。这就是我选择你的原因。 - Jagannath

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接