I’m implementing what’s basically an event log system for a larger system. I used Single-table inheritance to build out the table.
The problem I’m having is figuring out how to build out the classes from the database. It’s easy enough for me to figure out what they are to load them into the database, but to pull them out and create objects and collections out of them is a little trickier. The only way I know of is to have a switch statement and hope that if someone implements a new object that they’ll update the switch, but that doesn’t seem practical.
I’m sure I’m getting something wrong about how I’m thinking of the factory pattern here.
You might want to look at how Hibernate does it. See the SingleTableEntityPersister if you are truly using single-table inheritance.
Or better yet… just use Hibernate/NHibernate or another ORM and don’t reinvent the wheel.
To be clear, I’m not a huge fan of ORMs, but phrases like “single-table inheritance” imply that you’re already trying to object-relational mapping the “manual” way, and you’d save yourself a lot of time by using a tool that does all the heavy lifting for you.
If you must do it yourself for whatever reason… well, as you can see, there are different methods, but typically you will need to use a discriminator column, and for that you will either need a map, a switch statement, or a consistent convention (e.g. the discriminator value has an obvious relationship to the class name and you can instantiate it directly with reflection). Switch statement is going to be the fastest and is probably the preferred approach for a fairly small number of derived classes.
Tools like Hibernate can’t do it that way because, obviously, it would require specialized knowledge about the specific hierarchy, which they don’t have. You do have that knowledge, so you can skip all the mapping/reflection and just use switch/case in a factory class somewhere. The fact that someone might forget to update it in the future isn’t really an argument… your factory should throw an exception as soon as it encounters an unknown discriminator value.
If you’re really that worried, make the discriminator an enum, and write a unit test for the factory that iterates through every known enum value and tries to instantiate it with the factory. That way the future maintenance programmer will find out right away if they missed something.
9