Reputation: 633
Let's say I have an abstract class, Element
, and an interface Model
.
Element
has a method setModel(Model model)
.
Say Element
instances reference a single Model
implementation instance commonly, for things like deserializing from ReST, serializing to SQL tuples, etc.
Every Element
subclass is associate with one specific Model
, but any Model
might be associated with any number of Element
classes, so something like this:
public abstract class Element<M extends Model> {
private M mModel;
public void setModel(M model) {
mModel = model;
}
}
And
public interface Model {
// .. stuff
}
Now let's say I want to create a factory that produces Elements from Models. Given that a Model might be connected to a number of Element classes, we can expect that we need to provide the specific class. So something like this in the end result:
ElementSubclass e = new ElementFactory(ElementSubclass.class).from(someModelInstance);
or....
ElementFactory factory = new ElementFactory(ElementSubclass.class);
for(Model model : listOfModels) {
ElementSubClass element = factory.from(model);
listOfElementSubClassInstances.add(element);
}
Getting there has been less straightforward than I'd have thought. I've ended up with something like:
public class ElementFactory {
private Class<? extends Element> mElementClass;
public <E extends Element> ContentModelElementFactory(Class<E> elementClass) {
mElementClass = elementClass;
}
public <E extends Element> E from(Model model) {
try {
Element e = mElementClass.newInstance();
e.setModel(model);
return (E) e;
} catch (Exception ex) {
//
}
return null;
}
}
Seems a little shaky, and lint complains about both the call to setModel
and the cast on the line beneath.
I'd considered something like new ElementFactory<ElementSubclass>(ElementSubclass.class)
but that reads poorly - we already designated element subclass once, it seems heavy-handed to do so as both a type and an argument.
There's also the static version, like public static <E extends Element> E create(Class<E> clazz, Model model)
but obviously it's not a reusable as a true factory and seems a little less graceful.
Is there a better way to express this idea?
Upvotes: 1
Views: 101
Reputation: 43661
Since generic types are erased, you have to pass your ElementSubclass
to the factory, no way around that.
If you're irritated by new ElementFactory<ElementSubclass>(ElementSubclass.class)
then write a generic static method like public static <E extends Element> ElementFactory<E> of(Class<E> elementClass)
. This will give you code like:
ElementFactory<ElementSubclass> factory = ElementFactory.of(ElementSubclass.class);
Which feels somewhat better.
Upvotes: 1