Singleton – Wikipédia, a enciclopédia livre

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 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.

Como fazer a implementação do Singleton[editar | editar código-fonte]

1. Deixar o construtor privado, pois assim ninguém deve conseguir instanciar a classe, apenas o próprio Singleton.

2. Criar um atributo privado e estático do mesmo tipo da classe (instance). Algumas linguagens não tipadas não irão precisar do tipo, caso do PHP, por exemplo.

3. Método getInstance() é o principal ponto da classe. Ele verifica se a variável instance já foi iniciada, caso não tenha sido, ele faz sua criação pela primeira e única vez.

4. Para fazer a conexão, devemos chamar o getInstance da seguinte forma: ClasseSingleton.getInstance().

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:

public class SingletonDuplaVerificacao {  	private static SingletonDuplaVerificacao instance;  	private SingletonDuplaVerificacao() {}  	public static SingletonDuplaVerificacao getInstance() { 		if(instance == null) { 			synchronized(SingletonDuplaVerificacao.class) { 				if(instance == null) { 					instance = new SingletonDuplaVerificacao(); 				} 			} 		} 		return instance; 	}  }     Como usar:          1: Deixar o construtor privado, assim evitando qualquer criar um NEW.         2: Atributos privados e Estatico do mesmo tipo da classe instance         3: Metodo getInstance(); 

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  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() 

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

Segue um exemplo de Singleton em Typescript.

class MyClass {   private static instance: MyClass | undefined;    private constructor() {}    public static getInstance(): MyClass {     if (!this.instance) {       this.instance = new MyClass();       return this.instance;     } else {       return this.instance;     }   } } 

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 24 de agosto de 2016 

Ver também[editar | editar código-fonte]