Singleton

Origem: Wikipédia, a enciclopédia livre.
Ir para: navegação, pesquisa
Diagrama UML de uma classe singleton.

Singleton é um padrão de projeto de software (do inglês Design Pattern). Este padrão garante a existência de apenas uma instância de uma classe, mantendo um ponto global de acesso ao seu objeto.

Nota linguística: O termo vem do significado em inglês para um um conjunto (entidade matemática) que contenha apenas um elemento.[1]

Alguns projetos necessitam que algumas classes tenham apenas uma instância. Por exemplo, em uma aplicação que precisa de uma infraestrutura de log de dados, pode-se implementar uma classe no padrão singleton. Desta forma existe apenas um objeto responsável pelo log em toda a aplicação que é acessível unicamente através da classe singleton.

Onde Usar[editar | editar código-fonte]

Quando você necessita de somente uma instância da classe, por exemplo, a conexão com banco de dados, vamos supor que você terá que chamar diversas vezes a conexão com o banco de dados em um código na mesma execução, se você instanciar toda vez a classe de banco, haverá grande perda de desempenho, assim usando o padrão singleton, é garantida que nesta execução será instânciada a classe somente uma vez. Lembrando que este pattern é considerado por muitos desenvolvedores um antipattern, então, cuidado onde for utilizá-lo. [2]

Exemplos[editar | editar código-fonte]

Em Perl 5[editar | editar código-fonte]

Segue um exemplo em Perl 5 de uma das formas de implementar uma classe Singleton com a orientação a objetos nativa:

package Singleton {

  our $_instance;
  
  # construtor
  sub instance {
      my $class = shift;

      # constrói $_instance caso seja undef
      $_instance = bless {}, $class unless $_instance;
      
      return $_instance
  }
}

Em Python 2.7[editar | editar código-fonte]

Segue um exemplo em Python 2.7 de uma das formas de implementar uma classe Singleton (Utilizando o __new__):

class Singleton(object):

    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(Singleton, cls).__new__(
                                      cls, *args, **kwargs)
        return cls._instance

Em C++[editar | editar código-fonte]

Segue um exemplo em C++ da implementação de uma classe Singleton:

 class MyClass
 {
    private:
       // atributo estático da "instância única"
       static MyClass *instance = 0;
       //construtor privado, não pode ser utilizado fora da classe 
       MyClass() {}
 
    public:
       // Função-membro que retorna sempre a mesma instância do objeto
       static MyClass& getInstance()
       {
          if (!instance) instance = new MyClass();
          return *instance;
       }
 };

Em Java[editar | editar código-fonte]

A partir da versão 1.5 do Java, a melhor abordagem utilizada para a definição de tipos Singleton é com a utilização de tipos Enum, tal como mencionado por Joshua Bloch em seu livro "Java Efetivo Segunda Edição Revisada". Observe um exemplo:

1 public enum Elvis
2 {
3     INSTANCIA;
4     
5     public void cantar(){ ... }
6 }

Em um dos parágrafos do Item 3 do livro de Joshua Bloch, ele diz:

"Essa abordagem é funcionalmente equivalente à abordagem de campo público, exceto por ser mais concisa, fornecer o mecanismo de serialização facilmente e fornecer uma garantia sólida contra a instanciação múltipla, mesmo no caso de serialização sofisticada ou ataques de reflexão. Embora ela ainda tenha que ser amplamente adotada, um tipo enum com apenas um elemento é a melhor maneira de implementar um singleton."

Em C#[editar | editar código-fonte]

Segue um exemplo em C# da implementação de uma classe Singleton:

using System;

public class MyClass
{
   private static MyClass instance;

   private MyClass() {}

   public static MyClass Instance
   {
      get 
      {
         if (instance == null)
         {
            instance = new MyClass();
         }
         return instance;
      }
   }
}

Em Delphi[editar | editar código-fonte]

Abaixo segue um exemplo de como implementar uma classe Singleton:

interface
type
  TSingleton= class
  private
    class var FInstance: TSingleton;
    class function GetInstance: TSingleton; static;
  public
    class property Instance : TSingleton read GetInstance;
  end;
implementation 
  class function TSingleton.GetInstance: TSingleton;
  begin
    If FInstance = nil Then
      FInstance := TSingleton.Create();//objeto instanciado através do Finstance  
    Result := FInstance;//retorna o objeto
  end;

Em PHP[editar | editar código-fonte]

Aviso importante: Singleton em PHP é considerado um anti-pattern por causa da life cycle request/response que aplicações PHP normalmente utilizam.

<?php
namespace DesignPattern\AntiPattern;

class Singleton
{
	private static $instance;

        /**
         * Evita que a classe seja instanciada publicamente.
         *
         * @return void
         */
        private function __construct() 
        {
        }


        /**
         * Evita que a classe seja clonada.
         *
         * @return void
         */
        private function __clone() 
        {
        }

        /**
         * Método unserialize do tipo privado para prevenir a 
         * desserialização da instância dessa classe.
         *
         * @return void
         */
        private function __wakeup()
        {
        }
        
        /**
         * Testa se há instância definida na propriedade, 
         * caso sim, a classe não será instanciada novamente.
         *
         * @return DesignPattern\AntiPattern\Singleton
         */
	public static function getInstance()
	{ 
		if (!isset(self::$instance)) { 
			self::$instance = new self; 
		}

		return self::$instance;
	}
}

Em Ruby[editar | editar código-fonte]

require 'singleton'

class Foobar
    include Singleton
end

Em VB.NET[editar | editar código-fonte]

 Public Class MyClass
    Private Shared _instancia As MyClass
    Private Shared objetoSincronia As New Object
    
    Private Sub New()
    End Sub
    
    Public Shared Function getInstancia() As MyClass
        If _instancia Is Nothing Then
            SyncLock objetoSincronia
                If _instancia Is Nothing Then _instancia = New MyClass
            End SyncLock
        End If
        Return _instancia
    End Function
 End Class


Em ActionScript 3[editar | editar código-fonte]

package{
	public class ExemploSingleton {
		private static var instance:ExemploSingleton;
		
		public function ExemploSingleton(enforcer:SingletonEnforcer) : void {
			if (enforcer == null)
				throw new Error("Só pode haver uma instância de ExemploSingleton");
		}

		public static function getInstance() : ExemploSingleton {
			if (instance == null)
				instance = new ExemploSingleton( new SingletonEnforcer );
			return instance;
		}
	}
}
//Para bloquear o acesso ao constructor.
class SingletonEnforcer {

}

Em C# (utilizando Generics)[editar | editar código-fonte]

public sealed class GenericSingleton<T> where T : class, new()
{
    private static T _instance;

    public static T GetInstance()
    {
        lock (typeof(T))
        {
            if (_instance == null)
                _instance = new T();

            return _instance;
        }
    }
}

// Teste do padrão Singleton
public class Car { public int Color { get; set; } }
public class Person { public string Name { get; set; } }

class Program
{
    static void Main(string[] args)
    {
        Car car = GenericSingleton<Car>.GetInstance();
        car.Color = 1;
        Person per = GenericSingleton<Person>.GetInstance();
        per.Name = "John";

        Car car2 = GenericSingleton<Car>.GetInstance();
        car.Color = 2;
    }
}

Obs: Esta solução não impede a criação de múltiplas instâncias das classes Car e Person. Como a classe genérica GenericSingleton obriga que as classes passadas no parâmetro T tenham um construtor público, é possível criar instâncias em qualquer trecho de código através de construções do tipo: Car car3 = new Car();.

Em Kotlin[editar | editar código-fonte]

Segue um exemplo de Singleton em Kotlin.

  public object Singleton {
    public fun facaAlgumaCoisa() {
      //Aqui será feito alguma coisa legal
    }
  }
 
  // O singleton é usado assim:
  Singleton.facaAlgumaCoisa()

Benefícios[editar | editar código-fonte]

  • Permite o controle sobre como e quando os clientes acessam a instância.
  • Várias classes singleton podem obedecer uma mesma interface, permitindo assim que um singleton em particular seja escolhido para trabalhar com uma determinada aplicação em tempo de execução.
  • Com apenas uma implementação interna do singleton pode-se fazer com que o singleton crie um número controlado de instâncias.
  • É mais flexível que métodos estáticos por permitir o polimorfismo.

Contras[editar | editar código-fonte]

  • Acoplamento: Usando Singleton você estará acoplando o seu código em uma implementação estática e específica. Isso faz o seu código dependente dessa classe e impede, por exemplo, criar mocks em testes unitários.
  • Escopo: Se você por alguma razão decidir que para determinado componente da aplicação você precisa de outra implementação terá que alterar manualmente todas as classes.
  • Falsa segurança: No java, por exemplo, não existe uma classe apenas por JVM. O conceito de carregamento de classes em java é feito por ClassLoader.

Referências

  1. «singleton - definition of singleton in English from the Oxford dictionary - definition 1.4». www.oxforddictionaries.com. Consultado em 2016-08-24. 
  2. Quando você necessita de somente uma instância da classe, por exemplo, a conexão com banco de dados, vamos supor que vc terá que chamar diversas vezes a conexão com o banco de dados em um código na mesma execução, se você instanciar toda vez a classe de banco, haverá grande perda de desempenho, assim usando o padrão singleton, é garantida que nesta execução será instânciada a classe somente uma vez. Lembrando que este pattern é considerado por muitos desenvolvedores um anti-pattern, então, cuidado onde for utilizá-lo.Clube da Programação - Sobre design patterns: Singleton | url: http://www.clubedaprogramacao.com

Aula sobre design patterns - Singleton | url: http://www.clubedaprogramacao.com

Exemplo do uso de Singleton em aplicativo JSE | url: http://www.patternizando.com.br

[http://www.dsc.ufcg.edu.br/~jacques/cursos/map/html/pat/singleton.htm/ Singleton | url: http://www.dsc.ufcg.edu.br