VB .NET  - O padrão Singleton


Este artigo discute conceitos e a implementação do padrão Singleton no VB.NET.

Veja também o artigo : Conceito : Design Patterns 

Conceitos

Se você tem um conhecimento básico sobre a programação orientada a objetos deve saber que para criar uma instância de uma classe você deve chamar o construtor da classe usando a palavra chave New. Desta forma para criar uma instância da classe Teste podemos fazer a chamada para o construtor sem argumentos:

New Teste()

A cada chamada do construtor da classe um objeto é criado, assim,  se você chamar o construtor da classe 3 vezes você vai obter 3 instâncias da classe.

Mesmo que você não crie um construtor para sua classe o compilador do VB cria um construtor sem argumentos quando percebe que não existe um construtor.

Se a classe possuir um construtor com ou sem argumentos  o compilador VB não criará um construtor. Normalmente estes construtores possuem um modificador com acesso publico visto que eles foram criados para serem invocados fora da classe.

Existem ocasiões nas quais você pode desejar limitar o número de instâncias de uma classe a uma única instância. O exemplo clássico seria a implementação de uma classe Printer de forma a ter somente uma única instância da classe por vez. Com esta estratégia estamos prevenindo múltiplos processos que tentam controlar a impressora.

O padrão Singleton pode ser usado para alcançar este objetivo. Este padrão é efetivo por limitar o número máximo de instâncias de uma classe a somente uma única instância. Neste caso se mais que um objeto necessitar usar uma instância da classe Singleton estes objetos compartilham a mesma instância da classe Singleton.

A classe que implementa o padrão Singleton é chamada classe Singleton e possui um construtor privado que cria a instância da classe.

Como fazemos para obter somente um única instância de uma classe ?

A resposta reside nem utilizar um método estático (shared) da classe.

Uma classe Singleton deverá ter um método estático (shared) que chama o construtor para criar um instância da classe e retornar esta instância para quem chamou o método estático.

Mas você pode estar se perguntando: "Mas como eu vou chamar um construtor que é privado ?"

Ora , lembre-se que o método estático esta na mesma classe, e por este motivo, ele tem acesso a todos os membros da classe, incluindo o construtor privado da classe.

Então temos uma outra questão: "Se eu não posso criar uma instância da classe visto que seu construtor é privado, como eu vou chamar o método estático, responsável por criar uma única instância da classe, sem ter uma instância da classe ? "

Boa pergunta garoto, mas lembre-se que membros estáticos (shared) de uma classe podem ser invocados sem a necessidade de termos uma instância da classe.

Para limitar o número de instâncias a uma única instância o método estático (shared) precisa verificar se já existe uma instância criada. Se já existir uma instância ele deve simplesmente retornar uma referência a instância já criada. Se a instância não existir ele deve chamar o construtor da classe para criar uma instância.

implementando a classe Singleton no VB.NET

Crie um novo projeto do tipo Console Application com o nome de Singleton. A seguir inclua um novo modulo de classe a partir do menu Project -> Add Class e nomeie o arquivo como Singleton.vb.  A seguir inclua o seguinte código na classe Singleton.vb:

Public Class Singleton

        Public Shared instancia As Singleton
        Public Shared flag As Boolean
        Public texto As String

        Private Sub New()
            'construtor privado de forma a desabilitar outro a criar um objeto
        End Sub
        Friend Shared Function getSingletonObject() As Singleton
            If flag = False Then
                instancia = New Singleton()
                flag = True
                Return instancia
            Else
                Return instancia
            End If
        End Function
End Class

Temos em um único arquivo do tipo Class Library com o nome de Singleton.vb duas classes:

  1. A classe Singleton - que implementa o padrão Singleton

Vamos analisar a classe Singleton:

    Class Singleton
        Public Shared instancia As Singleton
        Public Shared flag As Boolean
        Public texto As String

        Private Sub New()
            'construtor privado de forma a desabilitar outro a criar um objeto
        End Sub
        Friend Shared Function getSingletonObject() As Singleton
            If flag = False Then
                instancia = New Singleton()
                flag = True
                Return instancia
            Else
                Return instancia
            End If
        End Function
    End Class

A classe possui 3 membros públicos sendo que dois são estáticos(shared). Para obter uma instância da classe além do método estático criamos as variáveis estáticas: instancia e flag.

        - Public Shared instancia As Singleton
        - Public Shared flag As Boolean
        - Public texto As String

A seguir temos o único construtor da classe usando o modificador Private (privado)  - Private Sub New()

A seguir temos o método getSingletonObject que é estático (Shared) e retorna uma nova instância da classe se não existir uma caso contrário ele retorna a instância que já existia.

Agora no arquivo Module1.vb inclua o seguinte código na classe Teste que ira servir para testar a implementação do padrão Singleton.

Module Module1

    Class teste
        Shared Sub main()
            Dim a As Singleton
            Dim b As Singleton

            a = Singleton.getSingletonObject
            a.texto = " << Singleton >> "
            Console.WriteLine(" a tem uma instância de Singleton     :  => " + a.texto)
            Console.WriteLine()
            b = Singleton.getSingletonObject
            Console.WriteLine(" b tem a mesma instância de Singleton :  => " + b.texto)
            Console.Read()
        End Sub
    End Class
End Module

 No código acima estamos chamando o método estático getSingletonObject na variável a do tipo SIngleton e a seguir atribuindo o valor " << Singleton >>" a variável texto.

Quando repetimos o processo para a variável b a classe deverá retornar a instância já criada  anteriormente o que pode ser comprovada pela impressão do conteúdo da variável texto na instância de b indicando que ela é a mesma instância de a.

Ao executar o projeto teremos o seguinte resultado:

Até o próximo artigo .NET ...

Referências:


José Carlos Macoratti