可觀察狀態

2006 年 1 月 5 日

當人們說一個方法不會改變物件的可觀察狀態時,他們是什麼意思?

將方法區分為會改變狀態和不會改變狀態的方法非常有用。不會改變狀態的方法(我稱之為查詢)可以在任何情況下使用,而不用擔心它們與其他方法的順序。

這裡的關鍵不在於它們不會改變任何狀態,而是它們不會改變可觀察的狀態。物件的可觀察狀態是可以從其查詢方法中檢測到的狀態 - 讓我用幾個簡短的範例來說明。

最簡單的範例是快取。想像一個像這樣的範圍類別。

# ruby
class MyRange
  attr_reader :start, :finish
  def initialize start, finish
    @start, @finish = start, finish
    @lengthCache = nil
  end
  def length
    @lengthCache = (@finish - @start) unless @lengthCache
    return @lengthCache
  end
end

這裡有一個lengthCache變數,在第一次存取時使用LazyInitialization填入。將值放入lengthCache明顯會改變物件的實際狀態。它不會改變可觀察狀態,因為你無法從外部得知物件的狀態已經改變。

我所謂的無法從外部得知,是指從另一個物件呼叫任何MyRange方法的結果,無論lengthCache值是否已填入,都會相同。

通常,你可以透過確保MyRange上的任何方法都使用length方法來取得範圍,而不是直接使用欄位,來達到這種效果。快取是一個明顯的狀態範例,其變更永遠不應該被觀察到。任何延遲初始化也不應該改變可觀察狀態,這也是正確的。