Design Patterns ou Padrões de Projeto: Singleton
Por Singleton ser o padrão mais simples de todos, o escolhi para ser o primeiro post. Assim vocês terão uma visal geral a respeito do conteúdo que iremos abordar nos próximos posts.
Definição
Garantir que uma classe tenha apenas uma instância e fornecer um ponto global de acesso a ela.
Diagrama UML
Quando pensamos em Singleton, pensamos em algo simples e sem riscos de problemas em nossas implementações, porém isto não é verdade, pois Singleton também gera problemas se implementando de forma errada. Vamos a seguir mostar exemplos retirados do livro Use a Cabeça - Padrões de Projeto.
A Fábrica de Chocolate
Todos sabemos que uma fábrica de chocolate moderna as caldeiras são controladas através de computadores, fazendo o processo de misturar o chocolate e leite, colocá-los em ebulição e passar para próxima fase da fabricação das barras de chocolate. A classe abaixo foi codificada com todo cuidado para evitar que coisas ruins acontecessem, como por exemplo, drenar 500 galões de misturas não fervidas, encher a caldeira enquanto ela já está cheia, ou até mesmo ferver uma caldeira vazia.
public class ChocolateBoiler
{
private bool _boiled;
private bool _empty;
private ChocolateBoiler()
{
_empty = true;
_boiled = false;
}
public void Fill()
{
if (IsEmpty())
{
_empty = false;
_boiled = false;
// preenche a caldeira com a mistura de leite e chocolate.
}
}
public void Drain()
{
if (!IsEmpty() && IsBoiled())
{
// drene o leite e o chocolate fervido.
_empty = true;
}
}
public void Boil()
{
if (!IsEmpty() && !IsBoiled())
{
// coloque a mistura em ebulição.
_boiled = true;
}
}
public bool IsEmpty()
{
return _empty;
}
public bool IsBoiled()
{
return _boiled;
}
}
Apesar classe ChocolateBoiler ter sido codificada tomando todos os cuidados possíveis para que nada de ruim possa acontecer, notamos que todo esse cuidado poderá ser ignorado se duas instâncias da classes ficarem frouxas.
Como resolveremos isto?
Singleton é a resposta. Implementariamos o seguinte:
private static ChocolateBoiler _uniqueInstance;
public static ChocolateBoiler GetInstance()
{
if (_uniqueInstance == null)
{
_uniqueInstance = new ChocolateBoiler();
}
return _uniqueInstance;
}
Assim como podemos ver com a implementação do padrão Singleton Clássico nada de errado poderia acontecer...
... isto se ...
... imagine que o controlador de caldeiras utilizasse vários segmentos ...
Como vocês podem ver temos um problema... Dois objetos foram criados.
"Parece que a Caldeira de Chocolate nos decepcionou; apesar de termos melhorado nosso código usando o Singleton Clássico, de alguma forma o método Fill() de ChocolateBoiler conseguiu começar a preencher a caldeira embora um lote de leite e chocolate já estivesse fervendo! Sãi 500 galões de leite (e chocolate) vazando." texto retirado do livro Use a Cabeça - Padrões de Projeto.
Quando temos mais de um segmento pode ocorrer conflito entre as instâncias comos vimos na ilustração acima, para resolver isto poderimos simplesmente sincronizar o método estático GetInstance() para que não permitisse que mais de um objeto fosse criado. Inserindo o objeto _synLock com o termo lock no método GetInstance() garantiriamos que os segmentos esperassem sua vez antes de poder executar o método. Chamariamos essa técnica de "trava duplamente verificada".
private static ChocolateBoiler _uniqueInstance;
private static object _synLock = new object();
public static ChocolateBoiler GetInstance()
{
if (_uniqueInstance == null)
{
lock (_synLock)
{
if (_uniqueInstance == null)
{
_uniqueInstance = new ChocolateBoiler();
}
}
}
return _uniqueInstance;
}
Porém a técnica mais segura e rápida seria:
private static readonly ChocolateBoiler _uniqueInstance =
new ChocolateBoiler();
public static ChocolateBoiler GetInstance()
{
return _uniqueInstance;
}
Ambas as técnicas demonstradas são seguras para execução em vários segmentos, isto pode variar de acordo com linguagem.
Bom pessoal, acho que o padrão Singleton já foi desvendado. Comentem a respeito deste post para que eu possa melhorar a qualidade dos próximos.
Design Patterns ou Padrões de Projeto
Design Patterns ou Padrões de Projeto, vocês já devem ter ouvido falar sobre este assunto, até mesmo lido a respeito, e deve ter se perguntado: "Quando vou usar isto? Quando sei que padrão utilizar?".
Pois bem, irei fazer uma sequência de posts detalhando um a um dos padrões GOF que são os mais conhecidos, mostrando a vocês exemplos no mundo real.
Uma breve introdução: (wikipedia)
Os padrões de projeto de software ou padrões de desenho de software, também muito conhecido pelo termo original em inglês: Design Patterns, descrevem soluções para problemas recorrentes no desenvolvimento de sistemas de software orientados a objetos. Um padrão de projeto estabelece um nome e define o problema, a solução, quando aplicar esta solução e suas conseqüências. Os padrões de projeto visam facilitar a reutilização de soluções de desenho - isto é, soluções na fase de projeto do software, sem considerar reutilização de código. Também acarretam um vocabulário comum de desenho, facilitando comunicação, documentação e aprendizado dos sistemas de software.
Padrões de Projeto GOF
Os padrões "GoF" são organizados em famílias de padrões: de criação, estruturais e comportamentais. Os padrões de criação são relacionados à criação de objetos, os estruturais tratam das associações entre classes e objetos e os comportamentais das interações e divisões de responsabilidades entre as classes ou objetos.
Padrões de Criação:
- Abstract Factory
- Builder
- Factory Method
- Prototype
- Singleton
Padrões Estruturais: - Adapter
- Bridge
- Composite
- Decorator
- Facade
- Flyweight, Proxy
Padrões Comportamentais: - Chain of Responsability
- Command
- Interpreter
- Iterator
- Mediator
- Memento
- Observer
- State
- Strategy
- Template Method
- Visitor