2011-10-16 44 views
2

在我的客戶端中,我想指定要在構建器生成的類中使用的策略。OOP:將設置傳遞給Builder類

但是,我無法將這些策略對象傳遞給構建器,因爲它們的初始化部分由構建器處理。然而,我仍然需要與建設者溝通使用哪個對象以及哪些附加參數來傳遞它。

這裏的生成器類

public class MarketGeneratorBuilder { 
    private MarketGenerator.Parameters parameters; 

    public MarketGeneratorBuilder(MarketGenerator.Parameters parameters) { 
     this.parameters = parameters; 
    } 

    public MarketGenerator build() { 
     return new MarketGenerator(
      parameters, 
      new GoodsGenerator(
       new UniformDistribution(
        new ValueRange(0,parameters.getNumberOfLevels()-1) 
       ) 
      ), 
      new ITGenerator(), 
      new OTGenerator(), 
      new IOTGenerator(
       new UniformDistribution(
        new ValueRange(1,parameters.getNumberOfLevels()-2) 
       ), 
       new BundlesGenerator(
        new ForwardMarkovDistribution(
         new MarkovDistribution.Parameters(
          new ValueRange(0,parameters.getNumberOfLevels()-1), 
          0.1, 
          0.1 
         ) 
        ), 
        new UniformDistribution(
         new ValueRange(1,parameters.getNumberOfGoodsToCreate()-1) 
        ) 
       ), 
       new BundlesGenerator(
        new BackwardMarkovDistribution(
         new MarkovDistribution.Parameters(
          new ValueRange(0,parameters.getNumberOfLevels()-1), 
          0.2, 
          0.2 
         ) 
        ), 
        new UniformDistribution(
         new ValueRange(1,parameters.getNumberOfGoodsToCreate()-1) 
        ) 
       ) 
      ) 
     ); 
    } 
} 

分佈(UniformDistribution,ForwardMarkovDistribution,ForwardMarkovDistribution和潛在更多的驚喜)現在是硬編碼的,而是應該由客戶來選擇。值範圍由Builder(ValueRange對象)定義。然而,一些分佈需要額外的參數(ForwardMarkovDistribution需要ValueRange,alpha,beta),這應該由客戶定義。

我能看到的唯一解決方案是將ValueRange從構造函數拉入setter。但它似乎是錯誤的,因爲它是該對象的一個​​重要領域。另外,我希望客戶端代碼不包含構建器的內部邏輯。更多像,

DistributionType levelDistribution = new DistributionType(Distributions.UNIFORM); 
DistributionType goodsDistribution = new DistributionsType(Distributions.MARKOV_FORWARD, 0.1,0.1); 

但在這種情況下,我不明白如何執行數據的完整性。這意味着當客戶端選擇Distributions.UNIFORM時,沒有更多的參數可以傳遞。或者在Distributions.MARKOV_FORWARD的情況下,他必須通過alpha和beta。

所以,我希望你能指出我更好的模式。謝謝!

回答

2

對於完全的靈活性,添加一個提供商/工廠爲每個分佈的:

interface DistributionProvider<D extends Distribution> { 
    D create(ValueRange vr); 
} 

class UniformDistributionProvider implements DistributionProvider<UniformDistribution> { 
    UniformDistribution create(ValueRange vr) { 
    return new UniformDistribution(vr); 
    } 
} 

class ForwardMarkovDistributionProvider implements DistributionProvider<ForwardMarkovDistribution> { 

    private final MarkovDistribution.Parameters params; 

    ForwardMarkovDistributionProvider(MarkovDistribution.Parameters pParams) { 
    params = pParams; 
    } 

    ForwardMarkovDistribution create(ValueRange vr) { 
    return new ForwardMarkovDistribution(vr, params); 
    } 
} 

// etc. 

(從MarkovDistribution.Parameters卸下ValueRange。)

基本上,每個提供程序都存儲分配的所有必需參數,但ValueRange除外。 然後客戶端可以實例化提供者以獲得他們想要的發行版,並使用適當的值對其進行配置。 構建器將獲得DistributionProvider的這些實例,並使用它們來創建分配,並傳遞一個ValueRange

0

我在這裏看到幾種不同的圖案。

  • 您可以有幾種不同的build方法。 buildUniform()buildMarkov(float alpha, float beta)
  • 您可以有幾個不同的建造者類:MarketGeneratorMarkovBuilder。他們可以有一個受保護的基類,方法是build。 [不知道我喜歡這一個]
  • 您可以在alphabeta值添加到parameters類,並拋出一個異常,如果它們不能用於MARKOV_FORWARD並拋出異常,如果他們可供UNIFORM
  • 如果整個建造者的ValueRange是恆定的,那麼我沒有理由爲什麼,如你所說,你不能將它添加到parameters或在建造者身上放置一個setter來注入它。
  • 您可能會考慮對所有常量子類使用依賴注入(以Spring方式)。建設者可以爲所有人提供安裝程序,而不是硬編碼。

希望這會有所幫助。