2012-11-25 15 views
3

考慮:生成數據的對象的許多實例。每次運行只產生一次這樣的數據是很好的。在Ruby的一個類的許多實例中記憶數據的好方法是什麼?

class HighOfNPeriods < Indicator 
    def generate_data 
    @indicator_data = DataStream.new 
    ([email protected]_data.data.count - 1).each do |i| 
     if i < @params[:n_days] 
     ... 
     @indicator_data.add one_data 
    end 
    end 

有不同params和不同@source_dataHighOfNPeriods不同實例。

這裏是指示如何使用:

class Strategy 
    attr_accessor :indicators 

    def initialize params 
    ... 
    end 

方法HighOfNPeriods.generate_dataStrategy中調用。每個Strategy都會得到一個新實例HighOfNPeriods,因此無法將其作爲某種全局值抽出。除此之外,它不應該是全球性的。

unless @indicator_data不起作用,因爲數據需要在許多HighOfNPeriods實例中共享。

所以,問題是:

What is a good way to memoize the instance variable `indicator_data` 
or the object `HighOfNPeriods` when there are many different instances, 
some of which have different data? 

一種解決方案是存儲使用ActiveRecord的數據,但是這並不是我真正想在這個時候做的方式,因爲:

  1. 不所有生成的數據可以預先生成,因爲有太多的params排列。看看它是否已經生成了之前生成的 ,然後根據需要生成(並保存)會更有意義。
  2. 生成數據並不需要很長時間。它可能會產生一次,每次運行使用 幾百次。
  3. 從對象中訪問數據比從數據庫中獲取數據要快。

紅寶石1.9.3

+0

請注意,當代碼透明時,實現記憶是非常容易的。我會說你的代碼設計不好,因爲你的'generate_data'方法不接受執行計算所需的參數,並且取決於你的對象的狀態。 – samuil

回答

1

使一個類變量@@indicator_data,其與[@params,@source_data]作爲密鑰和@indicator_data作爲值的散列。然後,在創作時,在@@indicator_data[[@params,@source_data]]上進行記憶。

class HighOfNPeriods < Indicator 
    @@indicator_data = {} 
    def generate_data 
    @indicator_data = @@indicator_data[[@params, @source_data]] ||= DataStream.new 
    ... 
    end 
end 
+0

這是如何工作的? '@ params'是散列,'@ source_data'是一個對象。 –

+1

關鍵是什麼都沒有關係。 '@@ indicator_data'爲每個'[@params,@source_data]'存儲一個'DataStream.new'實例。如果某個'[@params,@source_data]'已經存在'@@ indicator_data'中的'DataStream.new',則不會創建新的'DataStream.new'。 – sawa

+0

它像一個魅力工作。謝謝。 –

3

如果您不能在實例級別上記憶它,請上一層並使用類實例。

class Foo 
    # I used *args here for simplicity of the example code. 
    def generate_data *args 
    if res = self.class.cache[args] 
     puts "Data in cache for #{args.inspect} is #{res}" 
     return res 
    end 

    puts "calculating..." 
    p1, p2 = args 
    res = p1 * 10 + p2 
    self.class.cache[args] = res 
    res 
    end 

    def self.cache 
    @cache ||= {} 
    @cache 
    end 
end 


puts Foo.new.generate_data 1, 2 
puts Foo.new.generate_data 3, 4 
puts Foo.new.generate_data 1, 2 
# >> calculating... 
# >> 12 
# >> calculating... 
# >> 34 
# >> Data in cache for [1, 2] is 12 
# >> 12 
+0

我非常喜歡這個解決方案。和你的解釋。我不想使用類變量,我對這個解決方案感覺更好,這幫助我解決了我的特定問題。 –

相關問題