I'm working on an existing code base and am trying to reduce a lot of duplication and gain some polymorphic behavior. Right now I have a type of domain object with an abstract base class and two (at the moment) subclasses. In our domain we have a need sometimes to create pdf documents of these objects and send them as mail attachments, write them over HTTP, etc. The appearance of the pdf will of course differ a bit between the subclasses, but I don't feel like the domain objects should know about pdf files or how they should render and so on.
I have extracted an interface for building pdf documents from these objects. This interface is implemented by one class per subclass of the domain object, and I also have a factory method that decides what implementation should be used. Currently it makes this decision by checking the runtime type of the object, and if nothing matches, it just returns a "null builder" that creates an empty pdf.
I think I am on to something in the sense that I have achieved some SoC and deleted a lot of duplication, but I am not sure if the design is sound. I kind of get a knee-jerk reaction from checking runtime types for one thing, but something tells me that the fact that it happens in a factory and that I have a null implementation to return makes it more OK.
If I were to write all of this from scratch today I would have gone down a different route entirely, but like everyone else I have limited time and I wanna go with the "2 minutes to better code" approach, meaning do improvements in small steps every now and then and the code will improve over time. I'm not very familiar with the pattern, but I think maybe a visitor pattern could be of use here?