有一个MyFactory
课,可以创建MyObject
。
使用反射完成实例化,调用下一个setter。
按照惯例,MyObject
类需要有一个公共默认构造函数(即没有参数)。
我们的MyFactory看起来像这样:
public class MyFactory extends AbstractFactory<MyObject>
{
public MyFactory()
{
super(MyObject.class);
}
@Override
public MyObject createObject()
{
MyObject objt = super.createObject();
objt.setStuff(stuff);
return objt;
}
}
它使用一个简单的抽象工厂:
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();
}
}
当人们想要覆盖工厂以创建扩展为MyObject
的对象(例如MyExtendedObject
)时,问题就开始了。
我们添加了一个构造函数来促进这一点。
protected MyFactory(Class<? extends MyObject> clazz)
{
super(clazz);
}
首先,这足以创建扩展工厂,例如:
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;
}
}
所以,一切正常,但显而易见的是人们想要使用泛型。所以,我们试图提供泛型。事情开始变得复杂。
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;
}
}
问题是,人们实际上可以覆盖这个类,但是有一个隐藏的陷阱。它们不应该调用默认构造函数。事实上,整个构造函数设计在这里看起来很破碎。
知道如何改善这个吗? 我觉得必须有一个最佳实践或模式来解决这个问题。
答案 0 :(得分:0)
不允许使用no-args构造函数。这没有用的方法。
删除它:
public class MyFactory <O extends MyObject> extends AbstractFactory<O>
{
protected MyFactory(Class<O> clazz)
{
super(clazz);
}
@Override
public O createObject()
{
O objt = super.createObject();
objt.setStuff(stuff);
return objt;
}
}
但实际上,为什么这样的课程存在呢?只需为每个子类创建一个工厂类:
public class MyFactorySub <MyObjectSubclass> extends AbstractFactory<MyObjectSubclass>
{
public MyFactorySub()
{
super(MyObjectSubclass.class);
}
@Override
public MyObjectSubclass createObject()
{
MyObjectSubclass objt = super.createObject();
objt.setStuff(stuff);
return objt;
}
}