在这种情况下,我选择合成而非继承是正确的吗?

时间:2013-10-22 05:27:14

标签: java oop inheritance data-structures

我正在编写二叉树作为学习练习的一部分。我试图适应删除二叉树中节点的两种方法: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());

OR

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
   }

}

delete的不同实现将需要一个单独的子类(导致类可能爆炸):

public class BtreeDelByMerge extends BinaryTree{

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

我对继承方法的质疑是BtreeDelByMerge不是Btree的一种类型,它的行为不会改变很多并且只为其中一个方法创建一个单独的子类似乎不自然。如果我想要一个带有插入的特定实现以及删除等的树,它也不会像组合方法一样。

在这种情况下继承方式有什么特别的优势吗?另外,提供选择是一个好主意吗?例如:Collections框架没有提供太多选择,因此实现是封装良好且一致但严格的。

1 个答案:

答案 0 :(得分:1)

我认为这取决于deleteNode的实施。如果它只是在节点本身上工作,那么你的第一种方法(策略方法)看起来干净而优雅。

如果通过使用类的受保护成员/方法可以使删除更有效的情况(或将来可能存在的情况),我会选择继承方法。

例如:假设您有一个内部哈希映射,可帮助您更快地遍历树,然后只需左/右/父行走,并使此映射受到保护。现在,如果您选择策略方法,您将无法使用该地图,您可能需要它来更快地删除。如果您选择继承方法并使地图受到保护,您可以改进原始算法以进行删除。

此外,这只是一项练习,但如果您在“现实生活”场景中遇到这样的困境,您需要记住决定API是一种承诺。你应该考虑我提到的要点。

  1. 制定策略 - 让其他人更容易注入行为。
  2. 继承 - 更容易使用类内部实现。