O documento discute o padrão de projeto Singleton, que garante que apenas uma instância de uma classe seja criada. Ele explica que o Singleton é um padrão criacional útil quando objetos como pools de conexão ou registros precisam ser instanciados apenas uma vez. O documento fornece um exemplo de como implementar o padrão Singleton em código, usando um atributo estático e um método getInstance() para retornar a única instância.
2. Sumário
Introdução
Padrões de Projeto
Padrão Singleton
Exemplo
Considerações Finais
Referências Bibliográficas
3. Introdução
O que é um padrão de projeto?
Um padrão de projeto é uma estrutura recorrente
no projeto de software orientado a objetos. Pelo
fato de ser recorrente, vale a pena que seja
documentado e estudado.
O que faz um padrão de projeto?
Um padrão de projeto nomeia, abstrai e identifica
os aspetos chave de uma estrutura de projeto
comum para torná-la útil para a criação de um
projeto orientado a objetos reutilizável.
4. Padrões de Projeto
Os padrões de projeto são observados através da
experiência de um desenvolvedor com projetos
de software, o que significa que os padrões são
descobertos, e não inventados.
Como eles fornecem soluções prontas para a
solução de problemas, existem diversas
vantagens no seu uso como:
a reutilização de códigos, modelos e arquiteturas,
a padronização de designs e boas práticas,
a criação de uma linguagem comum entre
desenvolvedores.
5. Padrões de Projeto
Podemos classificar os padrões de projeto de
várias maneiras, porém o mais comum é
classificá-los de acordo com os tipos de
problemas que eles resolvem.
De acordo com esse critério, os padrões podem
ser:
Padrões de Criação: que lidam com o problema da
criação de objetos;
Padrões Estruturais: que lidam com os
relacionamentos entre objetos;
Padrões Comportamentais: que lidam com os
algoritmos e a atribuição de responsabilidades aos
objetos.
6. Padrão Singleton
O Padrão Singleton é um padrão criacional
É garantido que apenas uma única instância do
objeto seja instanciada em todo o projeto.
Qual a funcionalidade disso?
Objetos que tratam de pools de conexão, saídas
gráficas, impressão, objetos que cuidam de registros
não devem ser instanciados mais de uma vez
Um outro uso do padrão SINGLETON é quando
queremos uma classe de Log para todo o sistema, sem
precisarmos utilizar recursos do sistema para instanciar
uma classe sempre que precisarmos gravar dados no
servidor.
7. Padrão Singleton
Alguns programadores devem estar pensando agora: Mas
isso é fácil! Basta eu ter uma variável global com a
instância do objeto e sempre acessar ela! O problema é que
essa variável sendo inicializada no começo da execução do
projeto, essa classe estará consumindo recursos mesmo
sem ser utilizada! Com o Singleton, a classe só é
instanciada quando você realmente precisa dela!
Como previnir que um objeto não seja instanciado mais de
uma vez?
Criar um construtor privado. Com isso, a classe só pode ser
instanciada dentro de algum dos seus próprios métodos!
public class Singleton {
private Singleton () { }
}
8. Padrão Singleton
Agora que só podemos instanciar a classe dentro de um método,
vamos fazer com que esse método nos garanta que apenas uma
classe seja inicializada. Para isso vamos ter uma variável estática
que guardará a instância do único objeto instanciado. Caso ela
esteja nula, a função irá instanciar o objeto e então retorná-lo
para o usuário. Caso ela já contenha uma instância, o método
apenas retorna o objeto. Em código, temos:
public class Singleton {
private static Singleton instancia = null;
private Singleton () { }
public static Singleton getInstance() {
if(instancia==null) instancia = new Singleton ();
return instancia;
}
}
9. Padrão Singleton
Pronto! Nossa classe agora é um Singleton! Não é
possível ter mais de uma instância desse objeto!
Como se faz para instanciar um objeto já que não
posso simplesmente dar um “new” nele?
Singleton c1 = Singleton.getInstance();
Singleton c2 = Singleton.getInstance();
Em nosso exemplo, c1 e c2 representam o
mesmo objeto!
10. Exemplo
Problema: Como garantir que UMA e SOMENTE
UMA instância de uma certa classe exista durante
toda a execução do sistema?
Na figura abaixo podemos ver a solução Singleton com UML.
11. Exemplo
Imagine a seguinte situação:
"Gostaria de criar uma classe que gerasse uma
conexão com meu banco de dados. Quando eu
acessar a primeira vez essa classe, será
construída uma conexão, mas no decorrer da
execução, caso exista mais acessos ao banco,
gostaria de utilizar a MESMA classe com a MESMA
conexão."
13. Exemplo
Para instanciar uma classe, ou seja, para criar um
objeto de uma classe, precisamos utilizar o
operador new.
Exemplo: conexao = new Conexao();
Quando instanciamos uma classe, ao utilizar new, o
PHP automaticamente faz a chamada ao método
__construct() definido na classe;
Um atributo estático (static) é instanciado somente
uma vez e é compartilhado por TODOS os
objetos da mesma classe; mesmo que você
possua vários objetos de uma mesma classe,
esse atributo será o mesmo para todos.
14. Exemplo
Sabendo desses conceitos, vamos ao nosso código:
Na linha 1 do código definimos a classe Conexao;
Na linha 3 definimos uma atributo de instância estática da
classe;
Na linha 5 criamos o método construtor - __construct() - da
classe; perceba que o método está marcado como
PRIVATE, isso indica que se tentarmos utilizar o operador
new com essa classe teremos um erro de execução,
EXCETO se utilizarmos internamente à classe;
Na linha 6 colocamos nosso código para executar a conexão
com o banco de dados. Esse código ficará dentro do
método construtor;
Na linha 11 definimos o método publico getInstancia(). Esse
será o único método visível da classe e será responsável
por recuperar o objeto instancia;
15. Exemplo
Na linha 12 executamos o teste condicional, se o atributo
instancia for false, ou seja, no primeiro acesso à classe,
ele entrará no bloco;
Na linha 13 criamos uma instância da classe Conexao.
Perceba que utilizamos o operador new, portanto o método
__construct() será chamado, criando uma conexão com o
banco de dados.
Mas o método __construct() é private!!
Claro, mas isso não proíbe que a PROPRIA classe acesse
esse método. Somente proíbe o acesso do "lado de fora" da
classe Conexao;
Na linha 16 retornamos o atributo instancia.
Note pelo código que o objeto instancia será criado apenas
UMA vez, note também que, independentemente de onde
estamos chamando a classe Conexao, o método
getInstancia() retornará SEMPRE o mesmo objeto.
16. Considerações Finais
Singleton:
um dos padrões mais simples,
um dos mais criticados e mal usados.
Os singletons são difíceis de escalar, pois é difícil garantir
uma única instância de um singleton em um cluster, onde
existem várias JVMs.
Um outro problema é que os singletons dificultam o hot
redeploy por permanecerem em cache, bloqueando
mudanças de configuração.
Por esses e outros problemas, deve-se ter cuidado com o
uso abusivo de singletons.
CUIDADO! A utilização dos Padrões de Projetos é uma
"faca de dois gumes". O abuso de Padrões pode "engessar"
o projeto, dificultando sua manuntenção.
17. Referências Bibliográficas
FREEMAN E.; FREEMAN. E; SIERRA, K.; BATES B. Head
First: Design Patterns. Sebastopol: O’Reilly, 2001.
Padrões de Projeto: Soluções Reutilizáveis de Software
Orientado a Objetos – “The Gang of Four”
http://www.elton.utfpr.net/Escola/Padrão%20Singleton.pdf
http://www.plugmasters.com.br/sys/materias/893/1/Padr
%F5es-de-Projeto%3A-Singleton