懶初始化
原文: lazyinitialization
設計 bliki
索引乙個變數(在oo語境中常為class的乙個字段)第一次訪問時才被初始化,這項技術叫做懶初始化,其常規形式如下(c#):
public fooclass foo
}若得到某個字段值的計算過程很耗時,你想推遲至真正用到它時再計算,這時適宜採用懶初始化。也就是說,這個字段很多情況下用不到,或我們為了迅速初始化這個object寧願把耗時的事往後拖,懶初始化通常很適合處理這些情況。
需要記住這是一項優化技術,一些值客戶端當即並不需要,它們被懶初始化,這種優化提高了響應性。與其他優化技術一樣,應到確實需要解決效能問題時再採用。
尤其是這項技術還可能導致除錯上的麻煩。比如在除錯過程中,你檢視乙個懶初始化字段,它被賦值的那一刻也就意味著系統發生了乙個狀態改變(儘管
可見狀態沒變,但實際狀態變了),而這在正常情況下(不需此字段時)並不發生,因此當你加上個除錯列印語句時,bug們好像無影無蹤,一直藏到周五下午才發難——記住我傳授你的這個捉蟲秘方噢
可見狀態
原文: observablestate
設計 bliki
索引人們說乙個方法不修改乙個object的可見狀態,這是什麼意思呢?
把修改狀態的方法和不修改的分開,這麼做很有用。不修改狀態的方法(我稱之為query)可以在任何上下文中呼叫,無需像別的方法那樣擔心它們的呼叫順序。
這裡的關鍵點並不是它們什麼狀態都不修改,而是不修改可見狀態。乙個object的可見狀態是那些通過query方法可以得到的狀態——還是看乙個快捷的例子吧。
最簡單例子是快取(cache),看下邊這個表示區間的class:
# ruby
class myrange
attr_reader :start, :finish
def initialize start, finish
@start, @finish = start, finish
@lengthcache = nil
enddef length
@lengthcache = (@finish - @start) unless @lengthcache
return @lengthcache
endend
我們有乙個變數lengthcache,應用
懶初始化技術,第一訪問時被填充。給lengthcache賦值顯然對這個object的實際狀態做了修改,但它的可見狀態並沒改變,因為你從外面看不到這個object的狀態變了。
我說「從外面看不到」意思是,不管lengthcache的值已經被填充了還是沒被填充,這個myrange object的任何方法被別的object呼叫所得到的結果都一樣。
實現myrange其他方法時,所有用到區間長度的地方都不直接讀lengthcache欄位,而是呼叫length方法獲得——這是達到上述效果的典型做法。快取的改變不應該是可見的,這是個明顯的例子。另外一點是,所有懶初始化過程都不應修改可見狀態。
Spring初始化Bean狀態
一 單例模式 在spring中其實是scope 作用範圍 引數的預設設定值 每個bean定義只生成乙個物件例項,每次getbean請求獲得的都是此例項 單例模式分為餓漢模式和懶漢模式 關於單例的餓漢,懶漢請參考 二 預設情況下為單例模式 餓漢 prototype多例項模式介紹 呼叫getbean時,...
直接初始化與拷貝 複製 初始化
認識這兩種初始化有助於我們加深對語言的理解,可以更好的優化 我們常見的幾種初始化的形式 string str1 first 拷貝初始化,編譯器允許把這句話改寫為string str first 但是string 類必須有 public 的拷貝 移動 建構函式 string str2 10,a 直接初...
直接初始化與拷貝 複製 初始化
std set和std map都有乙個insert和emplace成員函式,那麼,他們的區別是什麼呢?他們都往 set或map 裡增加乙個元素,區別在於新元素的構造上。emplace 使用直接構造,insert 使用複製 拷貝 構造。那麼直接構造和複製構造有什麼區別呢?認識這兩種初始化 構造 有助於...