我正在尝试做的是实现一个点击流数据生成器,可以很好地扩展。
我在想什么:
属性是类,例如每个用户都有某种浏览器。所以有一个浏览器类。对于语言,插件等也是如此....
对于每个Property,都有一个Factory为我创建一个属性的随机实例,例如新浏览器(“Firefox”)或新语言(“德语”)。可能的值存储在每个属性的文件中。
基本上所有这些工厂和财产类都在做同样的事情。现在我为每个房产都有一个单独的工厂,每个新房子我必须建立一个新的工厂。
我的问题是,是否有可能为我拥有的所有物业以及新的物业实施某种通用工厂。
这是我的代码:
public abstract class Property {
protected String value;
Random rand;
public Property(String value) {
this.rand = new Random();
this.value = value;
}
@Override
public String toString() {
return this.value;
}
}
public class Browser extends Property{
public Browser(String value) {
super(value);
}
}
public abstract class AbstractFactory implements IFactory{
List<String> valuesList;
FileReader fileReader;
BufferedReader bufferedReader;
Random rand;
public AbstractFactory(String inputFile) {
rand = new Random();
this.valuesList = new LinkedList<String>();
String line = null;
try {
fileReader = new FileReader(inputFile);
bufferedReader = new BufferedReader(fileReader);
while ((line = bufferedReader.readLine()) != null) {
valuesList.add(line);
}
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
import model.Browser;
public class BrowserFactory extends AbstractFactory{
public BrowserFactory(String inputFile) {
super(inputFile);
}
@Override
public Browser getInstance() {
return new Browser(valuesList.get(rand.nextInt(valuesList.size())));
}
}
答案 0 :(得分:0)
匈牙利表示法(技术上,系统匈牙利表示法)不受欢迎。不应使用I
前缀命名Java接口。如果查看Java SE documentation,您会看到没有一个以这种方式命名的接口。
因此,考虑到这一点,您可以将Factory
定义为:
public interface Factory<T> {
T getInstance();
}
然后AbstractFactory复制:
public abstract class AbstractFactory<T> implements Factory<T> {
最后,BrowserFactory可以简单地使泛型类型更具体:
public class BrowserFactory extends AbstractFactory<Browser> {
@Override
public Browser getInstance() {
如果你想创建一个具体的类,你需要一些统一的方法来创建类。如果它们都具有带String的构造函数,则可以使用反射:
public class FeatureFactory<T> extends AbstractFactory<T> {
private final Constructor<T> constructor;
public FeatureFactory(Class<T> featureType) {
try {
this.constructor = featureType.getConstructor(String.class);
} catch (ReflectiveOperationException e) {
throw new IllegalArgumentException(
"Cannot find/access (String) constructor in " + featureType, e);
}
}
@Override
public T getInstance() {
try {
return constructor.newInstance(
valuesList.get(rand.nextInt(valuesList.size())));
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
}
}
您必须传递一个Class对象才能工作。泛型在运行时被擦除,因此您无法仅从<T>
派生类。实际上,您会发现Java SE类的工作方式相同;有关示例,请参阅EnumSet和EnumMap。
另一种更简洁的方法是使用Java 8 Function:
public class FeatureFactory<T> extends AbstractFactory<T> {
private final Function<String, ? extends T> creator;
public FeatureFactory(Function<String, ? extends T> creator) {
this.creator = Objects.requireNonNull(creator,
"Creation function cannot be null");
}
@Override
public T getInstance() {
creator.apply(
valuesList.get(rand.nextInt(valuesList.size())));
}
}
可以通过以下方式调用:
FeatureFactory<Browser> browserFactory = new FeatureFactory<>(Browser::new);