簡體   English   中英

設計模式實現這種類型的延遲加載?

[英]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);

是否有任何延遲加載模式可以幫助這樣的事情? 我完全控制整個項目,因此我不受現有IProcessorIProcessorFactory接口的限制。 我可以想辦法做到這一點(可能是某種代表嗎?),但是它們中沒有一個看起來很干凈,我想通過在項目中擁有一百萬個不同的實現來避免這種事情失控。 任何幫助將不勝感激!

因此,有兩種類型的打算使我們的生活在這里的超級容易。 第一個是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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM