Java通用工厂模式实现

Java通用工厂模式实现,java,generics,design-patterns,factory,Java,Generics,Design Patterns,Factory,我想做的是实现一个clickstream数据生成器,它可以很好地扩展 我想的是: 属性是类,例如每个用户都有某种浏览器。所以有一个浏览器类。同样适用于语言、插件等 对于每个属性,都有一个工厂为我创建一个属性的随机实例,例如新浏览器(“Firefox”)或新语言(“德语”)。可能的值存储在每个属性的文件中 基本上,所有这些工厂和属性类都在做同样的事情。现在我有一个单独的工厂为每个属性和每个新的porperty我必须产生一个新的工厂 我的问题是,是否有可能为我拥有的所有属性和即将出现的新属性实现某种

我想做的是实现一个clickstream数据生成器,它可以很好地扩展

我想的是:

属性是类,例如每个用户都有某种浏览器。所以有一个浏览器类。同样适用于语言、插件等

对于每个属性,都有一个工厂为我创建一个属性的随机实例,例如新浏览器(“Firefox”)或新语言(“德语”)。可能的值存储在每个属性的文件中

基本上,所有这些工厂和属性类都在做同样的事情。现在我有一个单独的工厂为每个属性和每个新的porperty我必须产生一个新的工厂

我的问题是,是否有可能为我拥有的所有属性和即将出现的新属性实现某种通用工厂

这是我的代码:

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())));
}

}
公共抽象类属性{
保护字符串值;
随机兰德;
公共属性(字符串值){
this.rand=new Random();
这个值=值;
}
@凌驾
公共字符串toString(){
返回此.value;
}
}
公共类浏览器扩展属性{
公共浏览器(字符串值){
超级(价值);
}
}
公共抽象类AbstractFactory实现了IFactory{
资产负债表;
文件阅读器;
BufferedReader BufferedReader;
随机兰德;
公共抽象工厂(字符串输入文件){
rand=新随机数();
this.valuesList=新的LinkedList();
字符串行=null;
试一试{
fileReader=新的fileReader(inputFile);
bufferedReader=新的bufferedReader(文件阅读器);
而((line=bufferedReader.readLine())!=null){
价值列表。添加(行);
}
bufferedReader.close();
}捕获(IOE异常){
e、 printStackTrace();
}
}
}
导入模型浏览器;
公共类BrowserFactory扩展了AbstractFactory{
公共浏览器工厂(字符串输入文件){
超级(输入文件);
}
@凌驾
公共浏览器getInstance(){
返回新浏览器(valuesList.get(rand.nextInt(valuesList.size()));
}
}
匈牙利符号(技术上称为系统匈牙利符号)是不受欢迎的。Java接口不应使用
I
前缀命名。如果您查看,您将看到没有一个接口以这种方式命名

因此,考虑到这一点,您可以将
工厂定义为:

public interface Factory<T> {
    T getInstance();
}
公共接口工厂{
T getInstance();
}
然后AbstractFactory复制以下内容:

public abstract class AbstractFactory<T> implements Factory<T> {
公共抽象类AbstractFactory实现工厂{
最后,BrowserFactory可以简单地使泛型类型更加具体:

public class BrowserFactory extends AbstractFactory<Browser> {
    @Override
    public Browser getInstance() {
公共类BrowserFactory扩展了AbstractFactory{
@凌驾
公共浏览器getInstance(){
如果您想创建一个具体的类,您需要一些统一的方法来创建这些类。如果它们都有接受字符串的构造函数,您可以使用反射:

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);
        }
    }
}
公共类FeatureFactory扩展了AbstractFactory{
私人最终建造商;
公共特征工厂(类特征类型){
试一试{
this.constructor=featureType.getConstructor(String.class);
}捕捉(反射操作异常e){
抛出新的IllegalArgumentException(
无法在“+featureType,e”中找到/访问(字符串)构造函数;
}
}
@凌驾
公共T getInstance(){
试一试{
返回构造函数.newInstance(
valuesList.get(rand.nextInt(valuesList.size());
}捕捉(反射操作异常e){
抛出新的运行时异常(e);
}
}
}
您必须传递一个类对象才能进行反射。泛型在运行时会被删除,因此您不能仅从
派生类。事实上,您会发现Java SE类的工作方式是相同的;有关示例,请参阅和

另一种更简洁的方法是使用Java 8:

公共类FeatureFactory扩展了AbstractFactory{
私有最终函数创建者;
公共功能工厂(函数创建者){
this.creator=Objects.requirennull(creator,
“创建函数不能为空”);
}
@凌驾
公共T getInstance(){
creator.apply(
valuesList.get(rand.nextInt(valuesList.size());
}
}
这可以通过以下方式调用:

FeatureFactory<Browser> browserFactory = new FeatureFactory<>(Browser::new);
FeatureFactory浏览器工厂=新的FeatureFactory(浏览器::新);
匈牙利符号(从技术上讲,系统匈牙利符号)是不受欢迎的。Java接口不应使用
I
前缀命名。如果您查看,您会发现没有一个接口以这种方式命名

因此,考虑到这一点,您可以将
工厂定义为:

public interface Factory<T> {
    T getInstance();
}
公共接口工厂{
T getInstance();
}
然后AbstractFactory复制以下内容:

public abstract class AbstractFactory<T> implements Factory<T> {
公共抽象类AbstractFactory实现工厂{
最后,BrowserFactory可以简单地使泛型类型更加具体:

public class BrowserFactory extends AbstractFactory<Browser> {
    @Override
    public Browser getInstance() {
公共类BrowserFactory扩展了AbstractFactory{
@凌驾
公共浏览器getInstance(){
如果您想创建一个具体的类,您需要一些统一的方法来创建这些类。如果它们都有接受字符串的构造函数,您可以使用反射:

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);
        }
    }
}
公共类FeatureFactory扩展了AbstractFactory{
私人最终建造商;
公共特征工厂(类特征类型){
试一试{
this.constructor=featureType.getConstructor(String.class);
}捕捉(反射操作异常e){
抛出新的IllegalArgumentException(
无法在“+featureType,e”中找到/访问(字符串)构造函数;
}
}
@凌驾
公共T getInstance(){
试一试{
返回构造函数.newInstance(
valuesList.get(rand.nextInt(valuesList.size());
}