An object that doesn’t contain all of the data you need but knows how to get it.
簡單的想你可以想成有一個很大的 Object S,然後裡面有 A、B、C 欄位,每個裡面都還是一個很大包的 Object,而 Lazy Load 就是可以在讀取 S.A 的資料時,可以只需要將 S.A 載入到記憶體,而不用整個 S 都要載入到記憶體中。
在書中有提到四種方式,然後右邊箭頭代表適用的模式 :
接下來由範例來說明每種模式的樣子。
每一次訪問屬性時,先判斷有沒有,如果為空,則在去 load 值。( 怎麼感覺好像 cache ),但這也代表要訪問屬性時,需要透過方法。
Inheritance → Lazy Loading 常見問題
多餘的資料庫處理 → ripple loading
This will cause you to go to the database once for each object instead of reading them all in at once.
下面這個是書中的範例,但我第一眼看到時冒出兩個問題 :
class Supplier...
public List getProducts() {
if (products == null) products = Product.findForSupplier(getID());
return products;
}
}
然後又去找了其它的例如 wiki 的範例,我到覺得比較適合,雖然他和上面書中的範例有點相似,都是去記憶中拿,到這裡 new 物件的,事實上應該是不會隨這時間而變動,因此應該是不太會有像 cache 更新的問題。
class Fruit {
private static Map<FruitType, Fruit> types = new HashMap<>();
public static Fruit getFruitByTypeName(FruitType type) {
Fruit fruit;
if (!types.containsKey(type)) {
// Lazy initialisation
fruit = new Fruit(type);
types.put(type, fruit);
} else {
// OK, it's available currently
fruit = types.get(type);
}
return fruit;
}
}
這裡我用 js 簡單舉個例子,假設我們有多種產品,然後要根據產品類型產生相對應的物件,然後下面就有兩種寫法,一個是『 全載入 』而另一個就是『 需要那個才載入那個 』。
// 全載入,就算你只要用 COURSE 的方法
const ProductFactory = {
'ARTICLE': require('./article')
'COURSE': require('./course')
}
// Lazy Loading,當你需要的使後才 require 該物件
const ProductLazyLoadingFactory = new Proxy(
{},
{
get: (target, prop) => {
const product = _productFactory(prop)
return product
}
}
)
function _productFactory (category) {
switch (category) {
case 'ARTICLE':
return require('./article')
case 'COURSE':
return require('./course')
default:
throw new Error(`The category#${category} is nonexistent`)
}
}