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.