[英]Design Pattern for implementing this type of lazy loading?
我有很多類實現這樣的接口:
public interface IProcessor
{
Foo Foo { get; set; }
int Process();
}
我有一個生產這些產品的工廠,我不知道它們將生產多少產品。 問題是,檢索必要的Foo
對象是昂貴的,並且在調用Process
之前,該屬性實際上並未在IProcessor
使用。
所以,如果我的工廠有這樣的方法:
public IProcessor CreateProcessor(int fooId)
{
Foo foo = this.Context.GetFoo(fooId);
return new ImplementedProcessor { Foo = foo };
}
我每次都要打電話給GetFoo
。 我真正喜歡的是這樣的:
public IProcessor CreateProcessor(int fooId)
{
this.CurrentlyTrackedFooIds.Add(fooId);
return new ImplementedProcessor { Foo = what??? };
}
我們的想法是,在ImplementedProcessor
需要Foo
執行其Process
方法之前,它會排隊fooId,以便可以像以下那樣對它們進行批量檢索:
this.Context.GetAllFoosAtOnceCheaply(this.CurrentlyTrackedFooIds);
是否有任何延遲加載模式可以幫助這樣的事情? 我完全控制整個項目,因此我不受現有IProcessor
或IProcessorFactory
接口的限制。 我可以想辦法做到這一點(可能是某種代表嗎?),但是它們中沒有一個看起來很干凈,我想通過在項目中擁有一百萬個不同的實現來避免這種事情失控。 任何幫助將不勝感激!
因此,有兩種類型的打算使我們的生活在這里的超級容易。 第一個是Lazy
。 構造一個Lazy
對象時,為它提供一個返回值的函數。 然后當你要求Lazy
的值時,如果它沒有啟動則啟動該函數,如果函數未完成則等待該函數,然后返回該值。 它從不調用該函數兩次。 如果從未詢問過該Value
則甚至不會關閉該功能一次。
然后我們可以創建一個Lazy
對象的ConcurrentDictionary
,這樣我們就可以確保得到任何現有的Lazy
對象。 請注意,其GetOrAdd
方法是可觀察的原子。 我們可以確定字典不會用另一個Lazy
覆蓋現有的Lazy
對象; 它要么返回現有的,要么設置一個新的。 這意味着我們永遠不會在代表相同ID的兩個不同Lazy
對象上調用Value
。
畢竟,編碼並不多:
private ConcurrentDictionary<int, Lazy<IProcessor>> lookup =
new ConcurrentDictionary<int, Lazy<IProcessor>>();
public IProcessor CreateProcessor(int fooId)
{
var lazy = lookup.GetOrAdd(fooId, new Lazy<IProcessor>(Context.GetFoo));
return new ImplementedProcessor { Foo = lazy.Value };
}
從.NET 4.0開始,框架為此提供了一個Lazy<T>
類:
public interface IProcessor {
Foo Foo { get; }
int Process();
}
internal class ImplementedProcessor {
internal Lazy<Foo> LazyFoo {get;set;}
public Foo Foo {
get {
return LazyFoo.Value;
}
}
public int Process() {
...
}
}
public IProcessor CreateProcessor(int fooId) {
return new ImplementedProcessor {
LazyFoo = () => this.Context.GetFoo(fooId)
};
}
然而,這不會批量檢索Foo
- 這個過程將一個接一個地進行。 只有從未為某些ImplementedProcessor
項調用Process()
時,才能節省一些時間。
要做到這一點,你需要創建一個在檢索到第一個Foo
懶惰地初始化的緩存,並保留其余的Foo
以獲取緩存的值。 Lazy<T>
不適合這樣。 考慮向IProcessor
添加一個方法,以便在調用Process
之前為緩存獲取所需的fooId
,並添加一個檢索所有感興趣的ID的類。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.