2014-08-30 141 views
0

假設我們有一個包含以下XML文件:在這種情況下如何避免多繼承?

<document> 

    <tagA /> 
    <tagB /> 
    <tagC /> 
    <tag1 /> 
    <tag2 /> 
    <tag3 /> 
    <custom1/> 
    <custom2/> 

</document> 

,並假設我們有一個解析器對象掃描該文件。對於文件中找到的每個標籤解析器調用處理程序對象的相應方法:

class Handler{ 

    function tagA(){ ... } 
    function tabB(){ ... } 
    function tagC(){ ... } 
    function tag1(){ ... } 
    function tag2(){ ... } 
    function tag3(){ ... } 
    function custom1(){ ... } 
    function custom2(){ ... } 

} 

現在,假設我們要建立一個框架來處理上述類型的文件。爲了確保代碼的可重用性,我們可以在上面的類分成不同的(更專業)類:

class LettersHandler{ 

    function tagA(){ ... } 
    function tabB(){ ... } 
    function tagC(){ ... } 

} 

class NumbersHandler{ 

    function tag1(){ ... } 
    function tag2(){ ... } 
    function tag3(){ ... } 

} 

要爲上述文件代碼的處理程序,程序員可以採取框架的優勢,只實現了缺失的方法(使用OOP繼承):

class Handler extends LettersHandler, NumbersHandler{ 

    function custom1(){ ... } 
    function custom2(){ ... } 

} 

根據該文件的內容,程序員可以選擇只從一個類繼承,從兩個(如上面的例子),或無。

現在,假設該框架支持許多預先建立一個處理程序:

class LettersHandler{ ... } 
class NumbersHandler{ ... } 
class SymbolsHandler{ ... } 
etc... 

如果編程語言支持多重繼承,程序員可以從該框架提供一個或多個類繼承來處理特定的文件(根據文件中包含的標籤)。

現在,我的問題是:

什麼是實現上述情況,如果編程語言不支持多重繼承的最好方式,但只支持單繼承?

有沒有一種簡單的方法來使用多重繼承?

我讀過多繼承通常被認爲是不好的做法,但我真的不明白如何實現上述情況而不使用它。

回答

0
  1. 創建一個名爲TagHandler的基類。

    // A C++ incarnation of such a class. 
    class TagHandler 
    { 
        virtual processTag(std::string const& tagName, 
             ..., // Any additional arguments that makes sense 
            ) = 0; 
    
    }; 
    
  2. 提供一種機制,爲客戶基於標籤名註冊TagHandler秒。做出一些關於如何處理給定標籤名稱的多個客戶端註冊處理程序的策略決策。你想舉一個例外嗎?最後一個贏了嗎?你是否允許多個TagHandlers?

    class TagProcessor 
    { 
        public: 
        static void registerTagHandler(std::string const& tagName, 
                TagHandler* tagHandler) 
        { 
         // Do the needful to register the TagHandler based on policy. 
        } 
    }; 
    
  3. 提供在上面的類中以黑匣子方式處理標籤的函數。

    class TagProcessor 
    { 
        public: 
    
        static void processTag(std::string const& tagName, 
              ..., // Any additional arguments that makes sense 
              ) 
        { 
         // Look for the TagHandler(s) given the tag name. 
         // If found, call the processTag() function. 
         // Deal with non-existing TagHandler. 
        } 
    
    
    }; 
    
  4. 加工各種標籤創建的子類型TagHandler

    class TagAHandler : public TagHandler 
    { 
        public: 
        virtual processTag(std::string const& tagName, 
             ...) 
        { 
         // Do the needful to process the tag 
        } 
    }; 
    
  5. 註冊TagHandler是對付 「塔加」

    TagProcessor::register("tagA", new TagHandler()); 
    
  6. 呼叫TagProcessor::processTag在解析器代碼。

0

更改解析器,使其接受一個處理程序數組而不是一個處理程序,然後讓它爲每個標記依次調用每個處理程序。如果處理程序無法處理標記(通過測試方法的存在,或者基類的方法返回一些「未實現」的sigil值),則調用下一個處理程序。

如果無法修改解析器,請實現一個新的處理程序,它接受處理程序數組並將其委託給它們,就像它是上述修改過的解析器一樣。

這實質上是將結構從程序的類型移動到程序數據中的結構。

相關問題