Introdução
Na engenharia de software, um Padrão de Projeto descreve uma solução estabelecida para os problemas mais comumente encontrados em software Projeto. Ele representa as melhores práticas desenvolvidas ao longo de um longo período por meio de tentativa e erro de desenvolvedores de software experientes.
Design Patterns ganhou popularidade depois que o livro Design Patterns: Elements of Reusable Object-Oriented Software foi publicado em 1994 por Erich Gamma , John Vlissides, Ralph Johnson e Richard Helm (também conhecido como Gang of Four ou GoF).
Neste artigo, exploraremos os padrões de design criacionais e seus tipos. Também examinaremos alguns exemplos de código e discuta as situações em que esses padrões se encaixam em nosso projeto.
Padrões de design criacional
Os padrões de design criacional estão relacionados à maneira como os objetos são criados . Eles reduzem as complexidades e a instabilidade ao criar objetos de maneira controlada.
O novo operador é frequentemente considerado prejudicial, pois espalha objetos por todo o aplicativo. Com o tempo, pode se tornar um desafio alterar uma implementação porque as classes se tornam fortemente acopladas.
Os Creational Design Patterns resolvem esse problema desacoplando o cliente inteiramente do processo de inicialização real.
Neste artigo , discutiremos quatro tipos de padrão de design criacional:
- Singleton – garante que no máximo apenas uma instância de um objeto exista em toda a aplicação
- Factory Method – cria objetos de várias classes relacionadas sem especificar o objeto exato a ser criado
- Abstract Factory – Cria famílias de objetos dependentes relacionados
- Builder – Constrói objetos complexos usando uma abordagem passo a passo
Vamos agora discutir cada um desses padrões em detalhes.
Singleton Design Pattern
O Singleton Design Pattern tem como objetivo manter uma verificação na inicialização de objetos de uma classe específica, garantindo que apenas uma instância do objeto exista em toda a Java Virtual Machine.
Uma classe Singleton também fornece um único ponto de acesso global para o objeto, de forma que cada chamada subsequente ao ponto de acesso retorne apenas aquele objeto específico.
3.1. Exemplo de padrão Singleton
Embora o padrão Singleton tenha sido introduzido por GoF, a implementação original é conhecida por ser problemática em cenários multithread.
Então, aqui, nós ” vamos seguir uma abordagem mais otimizada que faz uso de uma classe interna estática:
Aqui, criamos uma classe interna estática que contém a instância da classe Singleton. Ele cria a instância apenas quando alguém chama o método getInstance () e não quando a classe externa é carregada.
Esta é uma abordagem amplamente usada para uma classe Singleton, pois não requer sincronização, é thread-safe , força a inicialização lenta e tem comparativamente menos clichê.
Além disso, observe que o construtor tem o modificador de acesso privado. Este é um requisito para a criação de um Singleton, já que um construtor público significaria que qualquer pessoa poderia acessá-lo e começar a criar novas instâncias.
Lembre-se, esta não é a implementação original do GoF. Para a versão original, visite este link do artigo Baeldung sobre Singletons em Java.
3.2. Quando usar o Singleton Design Pattern
- Para recursos que são caros de criar (como banco de dados objetos de conexão)
- É uma boa prática manter todos os registradores como Singletons, o que aumenta o desempenho
- Classes que fornecem acesso às definições de configuração do aplicativo
- Classes que contêm recursos que são acessados no modo compartilhado
Factory Method Design Pattern
O Factory Design Pattern ou Factory Method Design Pattern é um dos padrões de design mais usados em Java.
De acordo com GoF, este padrão “define uma interface para a criação de um objeto, mas permite que as subclasses decidam qual classe instan tiato. O método Factory permite que uma classe adie a instanciação para subclasses ”.
Esse padrão delega a responsabilidade de inicializar uma classe do cliente para uma classe de fábrica específica, criando um tipo de construtor virtual.
Para isso, contamos com uma fábrica que nos fornece os objetos, ocultando os detalhes reais de implementação. Os objetos criados são acessados usando uma interface comum.
4.1. Exemplo de padrão de design de método de fábrica
Neste exemplo, vamos criar uma interface Polygon que será implementada por várias classes concretas. Uma PolygonFactory será usada para buscar objetos desta família :
Vamos primeiro criar a interface Polygon:
Em seguida, vamos criar algumas implementações como Square, Triangle, etc. que implementam esta interface e retornam um objeto do tipo Polygon.
Agora podemos criar uma fábrica que leva o número de lados como um argumento e retorna a implementação apropriada desta interface:
Observe como o cliente pode contar com esta fábrica para nos fornecer um polígono apropriado, sem ter que inicializar o objeto diretamente.
4.2. Quando usar o Factory Method Design Pattern
- Quando se espera que a implementação de uma interface ou classe abstrata mude com frequência
- Quando a implementação atual não pode acomodar confortavelmente novas mudanças
- quando o processo de inicialização é relativamente simples, e o construtor requer apenas alguns parâmetros
Abstract Factory Design Pattern
Na seção anterior, vimos como o padrão de projeto Factory Method pode ser usado para criar objetos relacionados a uma única família.
Por outro lado, o Abstract Factory Design Pattern é usado para criar famílias de objetos relacionados ou dependentes. Às vezes, também é chamado de fábrica de fábricas.
Para obter uma explicação detalhada, consulte nosso tutorial Abstract Factory.
Builder Design Pattern
O Builder Design Pattern é outro padrão de criação projetado para lidar com a construção de objetos comparativamente complexos.
Quando a complexidade da criação de objetos aumenta, o Builder pattern pode separar o processo de instanciação usando outro objeto (um construtor) para construir o objeto.
Este construtor pode então ser usado para criar muitas outras representações semelhantes usando uma abordagem passo a passo simples.
6.1. Padrão do construtor Exemplo
O Builder Design Pattern original introduzido por GoF se concentra na abstração e é muito bom para lidar com objetos complexos, no entanto, o design é um pouco complicado.
Joshua Bloch, em seu livro Effective Java, introduziu uma versão melhorada do padrão builder que é limpo, altamente legível (porque faz uso de design fluente) e fácil de usar da perspectiva do cliente. Neste exemplo, discutiremos essa versão.
Este exemplo tem apenas uma classe, BankAccount que contém um construtor como uma classe interna estática:
Observe que todos os modificadores de acesso nos campos são declarados privados, uma vez que não queremos que objetos externos os acessem diretamente.
O construtor também é privado, de modo que apenas o Construtor atribuído a este classe pode acessá-lo. Todas as propriedades definidas no construtor são extraídas do objeto construtor que fornecemos como argumento.
Definimos BankAccountBuilder em uma classe interna estática:
Observe que declaramos o mesmo conjunto de campos que a classe externa contém. Quaisquer campos obrigatórios são necessários como argumentos para o construtor da classe interna, enquanto os campos opcionais restantes podem ser especificados usando os métodos setter.
Esta implementação também suporta a abordagem de design fluente, fazendo com que os métodos setter retornem o construtor objeto.
Finalmente, o método build chama o construtor privado da classe externa e passa a si mesmo como o argumento. O BankAccount retornado será instanciado com os parâmetros definidos pelo BankAccountBuilder.
Vejamos um exemplo rápido do padrão do construtor em ação:
6.2. Quando usar o padrão Builder
- Quando o processo envolvido na criação de um objeto é extremamente complexo, com muitos parâmetros obrigatórios e opcionais
- Quando um aumento no número de parâmetros do construtor leva a uma grande lista de construtores
- Quando o cliente espera representações diferentes para o objeto que foi construído
Conclusão
Neste artigo, aprendemos sobre padrões de design criacionais em Java. Também discutimos seus quatro tipos diferentes, ou seja, Singleton, Método de fábrica, Abstract Factory e Builder Pattern, suas vantagens, exemplos e quando nós os usamos.
Como sempre, os snippets de código completos estão disponíveis no GitHub.
Comece com Spring 5 e Spring Boot 2, através do curso Aprenda Spring:
> > VERIFIQUE O CURSO