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
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
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
Em Perl 5
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
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++
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
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#
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
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
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
require 'singleton' class Foobar include Singleton end
Em VB.NET
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
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)
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
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
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
- 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
- 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
- ↑ «singleton - definition of singleton in English from the Oxford dictionary - definition 1.4». www.oxforddictionaries.com. Consultado em 24 de agosto de 2016
- Singleton http://www.dsc.ufcg.edu.br
Ver também
- Abstract Factory
- Builder
- Factory Method
- Prototype