There's a class MyFactory
which creates a MyObject
. Instantiation is done using reflection, next setters are called. By our convention the MyObject
class needs to has a public default constructor (i.e. without parameters).
Our MyFactory looks like this:
public class MyFactory extends AbstractFactory<MyObject>
{
public MyFactory()
{
super(MyObject.class);
}
@Override
public MyObject createObject()
{
MyObject objt = super.createObject();
objt.setStuff(stuff);
return objt;
}
}
It uses a simple abstract factory:
public abstract class AbstractFactory <T>
{
private Class<? extends T> clazz;
public AbstractFactory(Class<? extends T> clazz)
{
this.clazz = clazz;
}
public T createObject()
{
return clazz.newInstance();
}
}
The problems began when people wanted to override the factory to create objects that are extended of MyObject
(e.g. MyExtendedObject
). We added a constructor to facilitate this.
protected MyFactory(Class<? extends MyObject> clazz)
{
super(clazz);
}
And in first instance that was enough to create extended factories, such as:
public class MyExtendedFactory extends MyFactory
{
public MyExtendedFactory()
{
super(MyExtendedObject.class);
}
@Override
public MyObject createObject()
{
// and this is a bit uggly
MyExtendedObject objt = (MyExtendedObject) super.createObject();
objt.setExtendedStuffToo(extendedStuff);
return objt;
}
}
So, everything works, but it's obvious that people wanted to use generics instead. So, we tried to provide generics. And then things started to get complicated.
public class MyFactory <O extends MyObject> extends AbstractFactory<O>
{
public MyFactory()
{
// but now this is uggly and not really correct.
super(Class<O> extends MyObject.class);
}
protected MyFactory(Class<O> clazz)
{
super(clazz);
}
@Override
public O createObject()
{
O objt = super.createObject();
objt.setStuff(stuff);
return objt;
}
}
The problem is, that people can actually override this class, but there's a hidden trap. They are not supposed to call the default constructor. In fact the whole constructor design looks broken here.
Any idea how to improve this ? I have the feeling that there must be a best-practice or pattern to fix this.
Aucun commentaire:
Enregistrer un commentaire