I can't figure out how to avoid parallel hierarchies in practice. e.g. Consider an application which has to create/save/edit notes on different levels, it's a java swing based application.
Domain Hierarchy:
AbstractNote < MonthNote
< DayNote
< ProductNote
read only View Hierarchy(shown on JTabPane each having JTable to show the specific note details)
AbstractNotePanel < MonthNotePanel
< DayNotePanel
< ProductNotePanel
notes editor hierarchy(shown when user clicks on on a particular note in a table row.
AbstractNoteEditorDialog < MonthNoteEditorDialog
< DayNoteEditorDialog
< ProductNoteEditorDialog
I read one way to avoid this is to use Visitor Pattern.here
But this doesn't seem to be applicable to my situation.
I'm quite happy with my above design as most of the common code is in abstract class(applying template method pattern there). In case if I have to create a new type of note e.g. YearNote then I have to create YearNotePanel and YearNoteEditorDialog in parallel which is quite acceptable for me cause I don't have to code a lot due to templating. Above all I want to avoid code smell in my design. Please suggest me alternate design in above scenario so that my code would be still modular.
Thanks
Saying "above all I want to avoid code smell in my design" is a commendable goal but always keep in mind that the core of design is to weigh costs.
In my applications, I usually have model classes and configuration. Configuration can be in the model (annotations, introspection methods) or as extra files.
The UI layer reads this config and then build the UI from it. That means my design looks like this:
AbstractNote < MonthNote
< DayNote
< ProductNote
NotePanel
NoteEditorDialog
This often works because the dialogs and panels are pretty generic. Of course, my generic UI layer is pretty complex because it has to handle each corner case. So while this may look like a much better design than yours if you just look at the number of files or the inheritance hierarchy, the code inside of my UI layer is much, much more complex than yours.
Additionally, if I add a feature / fix a bug in the UI layer, chances are much higher that I break something elsewhere (so a change in the code to make editing DayNote
more comfortable can break MonthNote
).
So unless you feel that you have a lot of code duplication that you could avoid easily or maintenance costs are high or you just have a few model types (and not 500), there is nothing wrong with your design as such.
An important API you can use here is the BeanInfo API. Get acquainted with it. On any java class (bean) you can define a meta-level BeanInfo class.
One usage is that in this way you might make a new Swing component, and in the IDE using the BeanInfo provide a table component properties. (In the NetBeans IDE you can add your own components to the component palettes, and operate in this way.) This goes with property editors (for picking a color / data / .. ).