Controllo dei membri e creazione di istanze nelle proprietà

5

Considera questo:

public MyClass
{
    private Resource _myResource;

    public Resource MyResource
    {
        get
        {
            if(_myResource == null)
            {
                _myResource = new Resource();
            }

            return _myResource;
        }
    }

    public void UseResource()
    {
        MyResource.DoSomething();
    }
}

È un modello riconosciuto o forse un anti-pattern? Non l'ho mai visto suggerito in nessun libro, ma viene visualizzato più e più volte nel codice che vedo. Penso che la logica di ciò sia che _myResource viene istanziato 'just in time'. Per me, sembra un po 'puzzolente. UserResource () accede a una proprietà pubblica all'interno della classe e la risorsa non può mai essere realmente accessibile tramite il membro privato - se qualcuno lo ha fatto, _myResource potrebbe essere nullo.

Forse a volte potrebbero essere necessarie delle prestazioni, ma generalmente preferirei creare un'istanza nel costruttore, o semplicemente avere un'istanza di Risorsa locale per il metodo.

Quindi questo è uno schema accettato o dovrebbe essere evitato?

    
posta Paul T Davies 28.09.2011 - 14:16
fonte

1 risposta

4

Questo è uno schema accettato. Si chiama inizializzazione pigra , un modello creativo . Di solito lo usi per motivi di prestazioni, spesso combinato con altri pattern, ad esempio il Pattern Proxy . Quando le risorse sono pesanti e non ne hai bisogno subito, allora questo è un buon approccio per assicurarti che siano inizializzate solo la prima volta che ne hai bisogno.

Wikipedia la definisce una " tattica di ritardare la creazione di un oggetto, il calcolo di un valore, o qualche altro costoso processo fino alla prima volta che è necessario ".

Gli ORM, ad esempio, utilizzano questo modello per eseguire inizializzazioni pigre di entità correlate, quindi non è necessario recuperare un intero grafo di oggetti aggregato in modo avido, ma solo quando è veramente necessario operare sulle entità correlate.

Maybe performance reasons may sometimes necessitate, but I would generally favour instantiating in the constructor, or just having an instance of Resource local to the method.

Certo, questo potrebbe essere un approccio più pulito. Ma se le risorse sono davvero costose da istanziare, l'inizializzazione pigra è un buon modo per gestirle. Vuoi davvero aspettare molto tempo per creare un'istanza di un oggetto che di per sé è leggero, ma a volte ha bisogno di una risorsa pesante?

To me, it seems a bit smelly. UserResource() is accessing a public property from within the class, and the resource can never really be accessed through the private member - if someone did, _myResource could be null.

Sembra davvero un po 'puzzolente e se viene usato ovunque e non per il suo scopo, allora puzza davvero. Come con tutte le ottimizzazioni: non optmize se non hai bisogno di un'ottimizzazione. Ma l'inizializzazione pigra può essere un grande vantaggio per la tua applicazione se usata correttamente. E poi il suo odore poco appariscente è un piccolo prezzo da pagare per il suo valore.

    
risposta data 28.09.2011 - 14:19
fonte