生成Pete继承结构中的对象存在着一个问题,即每次向该继承结构添加新的Pet类型时,必须将其添加为LiteralPetCreator.java中的项。如果在系统中已经存在了继承结构的常规的基础,然后在其上要添加更多的类,那么就有可能会出现问题。
您可能会考虑在每个子类中添加静态初始化器,以使得该初始化器可以将它的类添加到某个List中。
遗憾的是,静态初始化器只有在类首先被加载的情况下才能被调用,因此您就碰上了“先有鸡还是先有蛋”的问题:生成器在其列表中不包含这个类,因此它永远不能创建这个类的对象,而这个类也就不能被加载并置于这个列表中。
这主要是因为,您被强制要求自己去手工创建这个列表(除非您想编写一个工具,它可以全面搜索和分析源代码,然后创建和编译这个列表)。
因此,您最佳的做法是,将这个列表置于一个位于中心的、位置明显的地方,而我们感兴趣的继承结构的基类可能就是这个最佳位置。
这里我们需要做的其他修改就是使用工厂方法设计模式,将对象的创建工作交给类自己去完成。工厂方法可以被多态地调用,从而为您创建恰当类型的对象。
在下面这个非常简单的版本中,工厂方法就是Factory接口中的create()方法:
//: typeinfo/factory/Factory.java
package typeinfo.factory;
public interface Factory<T> { T create(); } ///:~
泛型参数T使得create*()可以在每种Factory实现中返回不同的类型。这也充分利用了协变返回类型。
在下面的示例中,基类Part包含一个工厂对象的列表。对于应这个由createRandom()方法产生的类型,它们的工厂都被添加到了partFactories List中,从而被注册到了基类中:
//: typeinfo/RegisteredFactories.java
// Registering Class Factories in the base class.
import typeinfo.factory.*;
import java.util.*;
class Part {
public String toString() {
return getClass().getSimpleName();
}
static List<Factory<? extends Part>> partFactories =
new ArrayList<Factory<? extends Part>>();
static {
// Collections.addAll() gives an "unchecked generic
// array creation ... for varargs parameter" warning.
partFactories.add(new FuelFilter.Factory());
partFactories.add(new AirFilter.Factory());
partFactories.add(new CabinAirFilter.Factory());
partFactories.add(new OilFilter.Factory());
partFactories.add(new FanBelt.Factory());
partFactories.add(new PowerSteeringBelt.Factory());
partFactories.add(new GeneratorBelt.Factory());
}
private static Random rand = new Random(47);
public static Part createRandom() {
int n = rand.nextInt(partFactories.size());
return partFactories.get(n).create();
}
}
class Filter extends Part {}
class FuelFilter extends Filter {
// Create a Class Factory for each specific type:
public static class Factory
implements typeinfo.factory.Factory<FuelFilter> {
public FuelFilter create() { return new FuelFilter(); }
}
}
class AirFilter extends Filter {
public static class Factory
implements typeinfo.factory.Factory<AirFilter> {
public AirFilter create() { return new AirFilter(); }
}
}
class CabinAirFilter extends Filter {
public static class Factory
implements typeinfo.factory.Factory<CabinAirFilter> {
public CabinAirFilter create() {
return new CabinAirFilter();
}
}
}
class OilFilter extends Filter {
public static class Factory
implements typeinfo.factory.Factory<OilFilter> {
public OilFilter create() { return new OilFilter(); }
}
}
class Belt extends Part {}
class FanBelt extends Belt {
public static class Factory
implements typeinfo.factory.Factory<FanBelt> {
public FanBelt create() { return new FanBelt(); }
}
}
class GeneratorBelt extends Belt {
public static class Factory
implements typeinfo.factory.Factory<GeneratorBelt> {
public GeneratorBelt create() {
return new GeneratorBelt();
}
}
}
class PowerSteeringBelt extends Belt {
public static class Factory
implements typeinfo.factory.Factory<PowerSteeringBelt> {
public PowerSteeringBelt create() {
return new PowerSteeringBelt();
}
}
}
public class RegisteredFactories {
public static void main(String[] args) {
for(int i = 0; i < 10; i++)
System.out.println(Part.createRandom());
}
}
/* 输出:
GeneratorBelt
CabinAirFilter
GeneratorBelt
AirFilter
PowerSteeringBelt
CabinAirFilter
FuelFilter
PowerSteeringBelt
PowerSteeringBelt
FuelFilter
*///:~
并非所有在继承结构中的类都应该被实例化,在本例中,Filter和Belt只是分类标识,因此您不应该创建它们的实例,而只应该创建它们的子类的实例。
如果某个类应该由createRandom()方法创建,那么它就包含一个内部Factory类。如上所示,重用名字Factory的唯一方式就是限定typeinfo.factory.Factory。
尽管您可以使用Collections.addAll()来向列表中添加工厂,但是这样做编译器就会表达它的不满,抛出一条有关“创建泛型数组”的警告,因此我们转而使用add()。createRandom()方法从partFactories中随机地选取一个工厂对象,然后调用其Create()方法,从而产生一个新的Part。