I am coding a Binary Tree as part of a learning exercise. I am trying to accommodate the two ways of deleting a node in a binary tree: DeleteByMerge and DeleteByCopy.
What is the best way to offer choice for a user to choose between these methods?
I am leaning towards a composition approach(like a strategy) :
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()
   }
}
Classes DeleteByMerge and DeleteByCopy implement the interface BtreeDelete, so I could wire up during instantiation like this:
BinaryTree btree = new BinaryTree(new DeleteByMerge());
OR
BinaryTree btree = new BinaryTree(new DeleteByCopy());
.
Inheritance Based approach:
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
   }
}
Different implementations for delete will demand a separate subclass(leading to a possible explosion of classes):
public class BtreeDelByMerge extends BinaryTree{
   protected boolean deleteNode(Node node){
       // Code for deleting a node by Merging
   }
}
My qualm with the Inheritance approach is BtreeDelByMerge is not a type of Btree, it's behaviour does not change by much and having a to create a separate subclass for just one of its methods seems unnatural. Also it does not tend as well as the composition approach if I wanted a tree with a particular implementation of insert along with delete etc.
Are there any particular advantages going the inheritance way in this case? Also, is it a good idea to offer the choice at all? For ex: The Collections framework does not offer too many choices, so the implementations are well encapsulated and consistent but rigid.
 
    