I am designing a set of small C++ classes which all implement a single interface. Let’s call the interface IHandler. It has only one method.
There are a bunch of Handlers, one for each type in our domain. Let’s call them FooHandler, BarHandler etc. There is also a PassiveHandler, which does nothing (this is used for domain objects who don’t need to be handled).
So our hierarchy could look nice and flat like this:
IHandler
|-PassiveHandler
|-FooHandler
|-BarHandler
| (...)
|-BazHandler
However, all the handlers need a data member, let’s call it domainObject, so I thought about extracting a common superclass Handler that just holds this object.
Also, all the handlers except PassiveHandler needs a second data member, let’s call it infoObject, so I thought about extracting another common superclass ActiveHandlerto hold this object. Now the hierarchy is looking a lot deeper, but we have removed some duplication.
IHandler
|-Handler
| |-PassiveHandler
| |-ActiveHandler
| |-FooHandler
| |-BarHandler
| | (...)
| |-BazHandler
Would you go with the shallow design, where the domainObject member declaration is duplicated in all classes, and the infoObject member declaration in most? Or would you prefer the more complicated hierarchy, where duplication is removed? Is it worth it just for these data members?
I’d choose the second, more hierarchical solution. Not only because the data member, but also because of your remark: “this is used for domain objects who don’t need to be handled”. Sounds like this is more like a nul-handler, which does nothing at all. Seems to be a good thing to pull it out of the tree, because you’re likely to introduce other functionality too that will only apply to ‘active handlers’.