2017-05-05 78 views
1

我想要做的是實現一個點擊流數據生成器,它可以很好地擴展。Java通用工廠模式實現

我在想:

的屬性是類,例如每個用戶都有某種瀏覽器。所以有一個瀏覽器類。相同的語言,插件等...

對於每個屬性有一個工廠,創建一個屬性的隨機實例,例如新的瀏覽器(「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()))); 
} 

} 
+1

你能證明你有試過嗎? –

+0

你想要什麼肯定是可能的,但我需要一些更多的信息來弄清楚你需要什麼。你確定像Builder這樣的東西可能不適合你嗎? –

+0

我想要什麼,頂部擺脫我擁有的所有工廠類(每個功能一個),都做同樣的事情。 Thema之間的唯一區別是不同的輸入路徑和getinstance方法的不同輸出類型。 – Joha

回答

0

匈牙利命名法(在技術上,系統匈牙利命名法)是令人難以接受的。 Java接口不應以I前綴命名。如果你看看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類以相同的方式工作。例如參見EnumSetEnumMap

另有些更簡潔的方法是使用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);