2009-05-21 75 views
1

我有一個派生的子類繼承基本類,它承載的是應該是相同的所有派生類的基本功能:可選功能的設計模式?

class Basic { 
public: 
    Run() { 
     int input = something->getsomething(); 
     switch(input) 
     { 
      /* Basic functionality */ 
      case 1: 
       doA(); 
       break; 
      case 2: 
       doB(); 
       break; 
      case 5: 
       Foo(); 
       break; 
     } 
    } 
}; 

現在的基礎上,派生類,我想「添加」更多case語句交換機。我在這裏有什麼選擇?我可以聲明虛函數只有在派生類要使用它們定義它們:

class Basic { 
protected: 
    virtual void DoSomethingElse(); 
public: 
    Run() { 
     int input = something->getsomething(); 
     switch(input) 
     { 
      /* Basic functionality */ 
      ... 

      case 6: 
       DoSomethingElse(); 
     } 
    } 
}; 


class Derived : public Basic { 
protected: 
    void DoSomethingElse() { ... } 
} 

但在任何派生類中轉變職能時,這將意味着,我將不得不修改我的基類,以反映這些變化。

是否有專門針對此類問題的設計模式?我購買了許多關於設計模式的書籍,但是我正在「按需」基礎上研究它們,所以我不知道我是否有這樣的模式。

回答

4

您可能會發現閱讀Chain of responsibility pattern有用,並以此方式重新考慮您的解決方案。

您也可以聲明'doRun'爲受保護的方法,並在基本默認情況下調用它。

default: 
    doRun(input); 

並在派生類中定義doRun。

這就是所謂的Template Method pattern

+0

我想我現在要去模板方法模式。我一定會閱讀並考慮在這裏列出的其他模式,但現在這可以被標記爲接受:) – 2009-05-21 09:49:31

1

處理此問題的正常方法是使用工廠。概述:

  • 創建提供功能的相關類的層次結構。
  • 創建一個工廠類,它的輸入,並創建依賴於輸入現在

的加分點類的權kindf的一個實例:

  • 創建reghisters類withn方案工廠 - 你需要指定輸入和類的類型來處理它

現在,當需要一個新的輸入時,你只需派生一個新的類並註冊它與工廠。 switch語句的需要消失。

+0

我會試着澄清一下我的推理:我不需要根據輸入派生:派生類不會生活在堆棧上。我只是想分離不同類型的邏輯,但仍然爲所有派生類保留一些「基本」邏輯。 – 2009-05-21 09:55:35

4

我想你需要的模式是鏈責任中也許戰略與動態調用表合併...

1

但在任何派生類中改變 功能時,這將意味着,我 將不得不編輯我的基類到 反映這些更改。

爲什麼會這樣呢?

我點亮你的評論 - 然後如果你選擇這種方法,你會有這些問題。其他人發佈了可以提供其他解決方案的答案 - 我會檢查這些答案,看看他們是否能夠幫助你。

+0

嗯,或許我寫得很差。當我更改函數的內容時,我不必這樣做,但是當我刪除一個函數或更改它的名稱時,我將不得不返回到Basic類以反映這些更改。另外,我不想結束一個擁有大量虛擬功能的'基礎'類;一個用於從它派生的任何類中的每個函數。 – 2009-05-21 09:34:26

+0

只有在Basic類需要虛函數的時候纔會出現這種情況......任何一段代碼是否會在Basic類對象上調用這些函數,或者它們只是在子類中用於私有用途? 如果每個對象的類的類型是已知的(也就是說,你不需要多態性,這似乎是這種情況),你不需要在基類中聲明虛函數。 – fortran 2009-05-21 09:58:11

1

如果您選擇值只是小的整數,我會通過查找表代替case語句。 (在這個例子中的動作都需要被編碼爲一個函數,所以你可以把函數指針放在表中)。然後,繼承的類可以將條目添加到表中。 (我猜這個表必須是一個實例屬性,它不能是靜態的)。

科林

1

А簡單的解決方案:

class Basic { 
    public: 
    void Run() { 
     const int input = ... 
     if (!(BaseProcess(input) || Process(input))) ... 
    } 

    vitual bool Process(int input) { return false; } 

    bool BaseProcess(int input) { 
     switch(input) { 
    ... 
     default: return false; 
     } 
     return true; 
    } 
... 

...,然後實現在子類的附加箱子處理()。 如果你需要支持2個以上的級別(即子類添加更多的情況),那麼你需要一個動態調度表。