Verificando membros e instanciando em propriedades

5

Considere isso:

public MyClass
{
    private Resource _myResource;

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

            return _myResource;
        }
    }

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

Este é um padrão reconhecido, ou possivelmente um anti-padrão? Eu nunca vi isso sugerido em nenhum livro, mas ele aparece de novo e de novo no código que vejo. Eu acho que a lógica disso é que _myResource é instanciado 'just in time'. Para mim, parece um pouco malcheiroso. UserResource () está acessando uma propriedade pública de dentro da classe, e o recurso nunca pode ser acessado através do membro particular - se alguém o fez, _myResource poderia ser nulo.

Talvez algumas razões de desempenho possam algumas vezes ser necessárias, mas eu geralmente gostaria de instanciar no construtor, ou apenas ter uma instância de Resource local para o método.

Então este é um padrão aceito, ou deveria ser evitado?

    
por Paul T Davies 28.09.2011 / 14:16
fonte

1 resposta

4

Este é um padrão aceito. É chamado de inicialização lenta , um padrão de criação . Você geralmente usa isso por motivos de desempenho, geralmente combinados com outros padrões, por exemplo, o Proxy Pattern . Quando os recursos são pesados e você não precisa deles imediatamente, essa é uma abordagem boa e limpa para garantir que eles sejam inicializados apenas na primeira vez que você precisar deles.

A Wikipedia chama isso de " tática de retardar a criação de um objeto, o cálculo de um valor ou algum outro processo caro até a primeira vez em que é necessário ".

ORMs, por exemplo, usam esse padrão para executar inicializações lentas de entidades relacionadas, portanto, você não precisa buscar todo um gráfico de objeto agregado avidamente, mas apenas quando realmente precisa operar nas entidades relacionadas.

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.

Claro, isso pode ser uma abordagem mais limpa. Mas se os recursos são realmente caros para instanciar, então a inicialização lenta é uma boa maneira de lidar com eles. Você realmente quer esperar muito tempo para instanciar um objeto que por si só é leve, mas ocasionalmente precisa de um recurso pesado?

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.

Parece realmente um pouco malcheiroso e se for usado em todos os lugares e não por seu propósito, então ele realmente fede. Como com todas as otimizações: Não otimize se você não precisa de uma otimização. Mas a inicialização lenta pode ser um grande benefício para sua aplicação quando usada corretamente. E então o seu cheiro discreto é um pequeno preço a pagar pelo seu valor.

    
por 28.09.2011 / 14:19
fonte