2013-10-22 70 views
0

我編碼一個二叉樹作爲學習練習的一部分。我試圖去適應在二叉樹中刪除節點的兩種方法:DeleteByMerge和DeleteByCopy。在這種情況下,我是否正確地選擇了繼承的組合?

爲用戶提供選擇這些方法的最佳方式是什麼?

我傾向於一個組合方法(如策略):

public class BinaryTree{ 

    BtreeDelete del; 
    public BinaryTree(){ 
     this.del = new DeleteByCopy(); 
    } 

    public BinaryTree(BtreeDelete del){ 
     this.del = del; 
    } 

    public boolean delete(Node node){ 
     // Common code 
     del.delete() 
    } 

} 

類DeleteByMerge和DeleteByCopy實現接口BtreeDelete,這樣我就可以在實例化線了類似這樣的:

BinaryTree btree = new BinaryTree(new DeleteByMerge()); 

BinaryTree btree = new BinaryTree(new DeleteByCopy()); 

。基於

繼承方法:

public class BinaryTree{ 

    public BinaryTree(){ 

    } 

    public boolean delete(Node node){ 
     // Common code 
     deleteNode(); 
    } 

    // An overriddable hook with a default implementation 
    protected boolean deleteNode(Node node){ 
     //By default implementation for DeleteByCopy is provided 
    } 

} 

不同實現刪除將要求一個獨立的子類(導致類可能爆炸):

public class BtreeDelByMerge extends BinaryTree{ 

    protected boolean deleteNode(Node node){ 
     // Code for deleting a node by Merging 
    } 
} 

我與繼承方法的疑慮是BtreeDelByMerge不是一種Btree類型,它的行爲不會變化太大,並且爲其方法之一創建單獨的子類似乎不自然。如果我想要一個具有插入的特定實現以及刪除等的樹,它也不會像構圖方法那麼好。

在這種情況下繼承方式有什麼特別的優勢嗎?另外,提供所有選擇是一個好主意嗎?例如:集合框架沒有提供太多的選擇,所以實現的封裝很好,一致但僵化。

+1

爲什麼'BtreeDelByMerge'不是'Btree'類型?我看到你沒有從'Btree'擴展它,但是你有它繼承'deleteNode()',所以我認爲你就是這麼做的。就我個人而言,我會在這裏繼承。如果你擔心太多的實現,允許人們通過構造函數即插即用幫助對象只會複雜化。 –

+1

看看[這篇文章](http://stackoverflow.com/questions/49002/prefer-composition-over-inheritance)。 'DeleteByCopy'和'DeleteByMerge'都提供了'deleteNode'方法,我認爲他們在這個問題上共享相同的接口是合適的。 –

+0

@ musical_coder是的,我編輯了從BinaryTree繼承的代碼。通過繼承方法,當涉及到連接不同的實現時,我如何提供與組合方法相同的靈活性? – ChrisOdney

回答

1

我認爲這取決於執行deleteNode。如果它所做的只是在節點本身上工作,那麼你的第一種方法(策略方法)看起來乾淨而優雅。

如果有一種情況(或將來可能存在的情況),通過使用受保護的成員/類的方法可以使刪除效率更高,我會選擇繼承方法。

例如:假設您有一個內部哈希映射,它可以幫助您更快地遍歷樹,然後只是步行左/右/父,並使該映射受到保護。現在,如果您選擇策略方法,則無法使用該地圖,而您可能需要更快地刪除該地圖。如果您選擇繼承方法並保護地圖,則可能可以改進刪除的樸素算法。另外,這只是一個練習,但如果你在「現實生活」場景中面對這樣的困境,你需要記住,決定一個API是一種承諾。你應該考慮我提到的要點。

  1. 制定策略 - 更容易讓別人注入行爲。
  2. 繼承 - 更容易使用類的內部實現。
+0

該死!這就是我真正開始繼承的原因!我肯定需要訪問很多通過策略無法實現的封裝元素,但在這種情況下,使用繼承意味着用戶的靈活性較低。正如我上面所問,如果繼承方法的情況下,你如何讓用戶連接一個具有不同插入,刪除等實現的樹? – ChrisOdney

+0

作出決定通常意味着妥協,你應該選擇什麼可能會更好地滿足你的需求。你也可以將兩者結合起來,但它可能並不那麼優雅。 – Avi

+0

如果您希望組合和訪問實現,請使用內部類(非靜態)。 – siledh

相關問題