After reading a number of questions regarding abstract classes and interfaces, I am still unsure about how I should go about designing my code, so at the risk of having missed a possible duplicate, here’s my situation.
I am working on a number of utility classes that are meant to handle a nasty hierarchy of a particular type of object. While the precise details of the object is irrelevant, it should suffice to say that it’s not a general solution whatsoever. So I started by writing a CustomNode and a CustomHierarchy class.
A bit later on I realized that it’s much smarter to produce a more general solution, which can be reused in different context and easily tested without having to create lots of mock instances of the aforementioned complicated class. I could easily provide all the common code in interfaces and abstract classes, and just provide the specific bits where they are needed! (this I believe is the whole point with OOP?)
So far I have:
-
an interface
Relatablewhich simply holds an enum of possible relations that nodes might have to one another, and a method signature ofgetRelation(Relatable other) -
an abstract class
Node<E>which implements theRelatableand contains all utility methods (e.g.addChild()orgetNextSibling(). The only method this class is missing is thegetRelation(Relatable other). -
a concrete class
Hierarchy<E>which will define how to build up the hierarchy of the nodes, starting from aCollection<E>which holds the data.
The idea is to extend the Node<E> and Hierarchy<E> classes with appropriate subclasses based on the problem at hand. The first two are done without any major hustle but I am having problems with the Hierarchy<E> class since it has a private method addNodeToHierarchy(E data) which tries to instantiate a Node<E> and place it in the hierarchy. This obviously fails as the node class is abstract and can’t be instantiated.
I understand why this is not working, but I am not sure how I should go about circumventing this problem. Is there a flaw in my design? Should I add a static createNewNode(E data) method in the Node<E> and use that instead? Another option I can think of is to detach the Node from getting the relation and go with a Relator interface instead. This can’t be a unique problem by any chance, so what’s “good practice” in this situation?
Thanks in advance,
Decide who should know how a
Node<E>must be constructed from from an instance ofE. It could be the instance ofE, it could be theNodeclass, it could be the Hierarchy, or it could be the caller ofaddNodeToHierarchy().If it’s the caller of
addNodeToHierarchy(), then either you make it take an instance ofNode<E>instead of an instance ofE, or you make it take an instance of someNodeFactory<E>, to which the method will delegate to transform the data into a node. This factory could also be passed as an argument to the hierarchy constructor if all the nodes are constructed by the same factory.