Padrões de Design em Java – Tutorial de Exemplo

Introdução

Padrões de design são muito populares entre os desenvolvedores de software. Um padrão de design é uma solução bem descrita para um problema de software comum.

Alguns dos benefícios de usar padrões de design são:

  1. Os padrões de design já estão definidos e fornecem uma abordagem padronizada pela indústria para resolver um problema recorrente, então economiza tempo se usarmos o padrão de design de maneira sensata. Existem muitos padrões de design Java que podemos usar em nossos projetos baseados em Java.
  2. O uso de padrões de design promove a reutilização que leva a um código mais robusto e altamente mantível. Isso ajuda a reduzir o custo total de propriedade (TCO) do produto de software.
  3. Como os padrões de design já estão definidos, torna nosso código fácil de entender e depurar. Isso leva a um desenvolvimento mais rápido e novos membros da equipe o entendem facilmente.

Os padrões de design Java são divididos em três categorias – criacionais, estruturais e comportamentais.

Este artigo serve como um índice para todos os artigos de padrões de design Java.

Padrões de Design Criacionais

Padrões de design criacionais fornecem soluções para instanciar um Objeto da melhor maneira possível para situações específicas.

1. Padrão Singleton

O padrão singleton restringe a instanciação de uma Classe e garante que apenas uma instância da classe exista na Máquina Virtual Java. A implementação do padrão singleton sempre foi um tópico controverso entre os desenvolvedores.

Nota: Saiba mais sobre o Padrão de Design Singleton.

2. Padrão de Fábrica

O padrão de design de fábrica é usado quando temos uma superclasse com várias subclasses e, com base na entrada, precisamos retornar uma das subclasses. Esse padrão retira a responsabilidade da instanciação de uma Classe do programa cliente para a classe de fábrica. Podemos aplicar um padrão singleton na classe de fábrica ou tornar o método de fábrica static.

Nota: Saiba mais sobre o Padrão de Design de Fábrica.

3. Padrão de Fábrica Abstrata

O padrão de fábrica abstrata é semelhante ao padrão de fábrica e é uma fábrica de fábricas. Se você estiver familiarizado com o padrão de projeto de fábrica em Java, você notará que temos uma única classe de fábrica que retorna as diferentes subclasses com base na entrada fornecida, e a classe de fábrica usa declarações if-else ou switch para alcançar isso. No padrão de fábrica abstrata, nos livramos do bloco if-else e temos uma classe de fábrica para cada subclasse e então uma classe de fábrica abstrata que retornará a subclasse com base na classe de fábrica de entrada.

Nota: Saiba mais sobre o Padrão de Fábrica Abstrata.

4. Padrão Builder

O padrão builder foi introduzido para resolver alguns dos problemas com os padrões de projeto de fábrica e fábrica abstrata quando o objeto contém muitos atributos. Este padrão resolve o problema com um grande número de parâmetros opcionais e estado inconsistente, fornecendo uma maneira de construir o objeto passo a passo e fornecer um método que realmente retornará o Object final.

Nota: Saiba mais sobre o Padrão de Construtor.

5. Padrão de Protótipo

O padrão de protótipo é usado quando a criação do Objeto é custosa e requer muito tempo e recursos, e você já possui um Objeto similar existente. Portanto, esse padrão fornece um mecanismo para copiar o Objeto original para um novo Objeto e então modificá-lo de acordo com nossas necessidades. Esse padrão usa a clonagem em Java para copiar o Objeto. O padrão de design de protótipo exige que o Objeto que você está copiando forneça o recurso de cópia. Isso não deve ser feito por nenhuma outra classe. No entanto, se deve usar a cópia rasa ou profunda das propriedades do objeto depende dos requisitos e é uma decisão de design.

Nota: Saiba mais sobre o Padrão de Protótipo.

Padrões de Design Estrutural

Os padrões de design estrutural oferecem maneiras diferentes de criar uma estrutura de Classe (por exemplo, usando herança e composição para criar um Objeto grande a partir de Objetos pequenos).

1. Padrão Adaptador

O padrão de design do adaptador é um dos padrões de design estrutural e é usado para que duas interfaces não relacionadas possam trabalhar juntas. O objeto que une essas interfaces não relacionadas é chamado de adaptador.

Nota: Saiba mais sobre o Padrão Adaptador.

2. Padrão Composto

O padrão composto é usado quando precisamos representar uma hierarquia parte-todo. Quando precisamos criar uma estrutura de maneira que os objetos na estrutura tenham que ser tratados da mesma maneira, podemos aplicar o padrão de design composto.

Nota: Saiba mais sobre o Padrão Composto.

3. Padrão de Proxy

O padrão de proxy fornece um espaço reservado para outro Object controlar o acesso a ele. Esse padrão é usado quando desejamos fornecer acesso controlado a funcionalidades.

Nota: Saiba mais sobre o Padrão de Proxy.

4. Padrão de Peso-Leve (Flyweight)

O padrão de design peso-leve (flyweight) é usado quando precisamos criar muitos Objects de uma Class. Como cada Object consome espaço de memória que pode ser crucial para dispositivos com pouca memória (como dispositivos móveis ou sistemas embarcados), o padrão de design peso-leve pode ser aplicado para reduzir a carga na memória, compartilhando Objects.

Implementação do pool de strings em Java é um dos melhores exemplos de implementação do padrão peso-leve.

Nota: Saiba mais sobre o Padrão de Peso-Leve.

5. Padrão de Fachada

O padrão de fachada é usado para ajudar as aplicações cliente a interagirem facilmente com o sistema.

Nota: Saiba mais sobre o Padrão de Fachada.

6. Padrão de Ponte

Quando temos hierarquias de interface tanto nas interfaces quanto nas implementações, então o padrão de design de ponte é usado para desacoplar as interfaces da implementação e para ocultar os detalhes de implementação dos programas cliente. A implementação do padrão de design de ponte segue a noção de preferir composição sobre herança.

Nota: Saiba mais sobre o Padrão de Ponte.

7. Padrão de Decorador

O padrão de design decorator é usado para modificar a funcionalidade de um objeto em tempo de execução. Ao mesmo tempo, outras instâncias da mesma classe não serão afetadas por isso, então o objeto individual obtém o comportamento modificado. O padrão de design decorator é um dos padrões de design estruturais (como o padrão de adaptador, padrão de ponte ou padrão composto) e usa classes abstratas ou interfaces com composição para implementar. Usamos herança ou composição para estender o comportamento de um objeto, mas isso é feito em tempo de compilação, e é aplicável a todas as instâncias da classe. Não podemos adicionar nenhuma nova funcionalidade ou remover qualquer comportamento existente em tempo de execução – é aqui que o padrão de decorator é útil.

Nota: Saiba mais sobre o Padrão Decorator.

Padrões de Design Comportamental

Padrões comportamentais fornecem uma solução para uma melhor interação entre objetos e como fornecer acoplamento fraco e flexibilidade para estender facilmente.

1. Padrão de Método de Modelo

O padrão de método de modelo é um padrão de design comportamental e é usado para criar um esboço de método e adiar algumas etapas de implementação para as subclasses. O método de modelo define as etapas para executar um algoritmo, e pode fornecer uma implementação padrão que pode ser comum para todas ou algumas das subclasses.

Nota: Saiba mais sobre o Padrão de Método de Modelo.

2. Padrão Mediador

O padrão de design do mediador é usado para fornecer um meio de comunicação centralizado entre diferentes objetos em um sistema. Se os objetos interagem entre si diretamente, os componentes do sistema estão fortemente acoplados entre si, o que torna o custo de manutenção mais alto e não flexível para estender facilmente. O padrão de mediador concentra-se em fornecer um mediador entre objetos para comunicação e implementar o acoplamento frouxo entre objetos. O mediador funciona como um roteador entre objetos, e pode ter sua própria lógica para fornecer uma forma de comunicação.

Nota: Saiba mais sobre o Padrão Mediador

3. Padrão de Chain of Responsibility

O padrão de chain of responsibility é utilizado para alcançar baixo acoplamento no design de software, onde uma solicitação do cliente é passada para uma cadeia de objetos para serem processados. Então, o objeto na cadeia decidirá quem irá processar a solicitação e se a solicitação precisa ser enviada para o próximo objeto na cadeia ou não.

Nós sabemos que podemos ter múltiplos blocos catch em um bloco de código try-catch. Aqui, cada bloco catch é uma espécie de processador para lidar com aquela exceção específica. Então, quando uma exceção ocorre no bloco try, ela é enviada para o primeiro bloco catch para ser processada. Se o bloco catch não for capaz de processá-la, ele encaminha a solicitação para o próximo Object na cadeia (ou seja, o próximo bloco catch). Se mesmo o último bloco catch não conseguir processá-la, a exceção é lançada fora da cadeia para o programa chamador.

Nota: Saiba mais sobre o Padrão de Chain of Responsibility.

4. Padrão de Observer

Um padrão de design de observador é útil quando você está interessado no estado de um Object e deseja ser notificado sempre que houver alguma alteração. No padrão de observador, o Object que observa o estado de outro Object é chamado de observador, e o Object que está sendo observado é chamado de sujeito.

O Java fornece uma plataforma integrada para implementar o padrão de observador por meio da classe java.util.Observable e da interface java.util.Observer. No entanto, não é amplamente utilizado porque a implementação é limitada e na maioria das vezes não queremos acabar estendendo uma classe apenas para implementar o padrão de observador, já que o Java não oferece heranças múltiplas em classes. O Java Message Service (JMS) utiliza o padrão de observador juntamente com o padrão mediador para permitir que as aplicações se inscrevam e publiquem dados para outras aplicações.

Nota: Saiba mais sobre o Padrão de Observador.

5. Padrão de Estratégia

O padrão de estratégia é usado quando temos vários algoritmos para uma tarefa específica, e o cliente decide a implementação real a ser usada em tempo de execução. O padrão de estratégia também é conhecido como padrão de política. Definimos vários algoritmos e permitimos que as aplicações do cliente passem o algoritmo a ser usado como parâmetro.

Um dos melhores exemplos desse padrão é o método Collections.sort() que recebe o parâmetro Comparator. Com base nas diferentes implementações das interfaces de comparador, os objetos são classificados de maneiras diferentes.

Nota: Saiba mais sobre o Padrão de Estratégia.

6. Padrão de Comando

O padrão de comando é usado para implementar um acoplamento fraco em um modelo de solicitação e resposta. Nesse padrão, a solicitação é enviada ao invocador e o invocador a repassa para o objeto comando encapsulado. O objeto de comando repassa a solicitação para o método apropriado do receptor para realizar a ação específica.

Nota: Saiba mais sobre o Padrão de Comando.

7. Padrão de Estado

O padrão de design de estado é usado quando um Object muda seu comportamento com base em seu estado interno. Se precisarmos alterar o comportamento de um Object com base em seu estado, podemos ter uma variável de estado no Object e usar um bloco de condição if-else para executar ações diferentes com base no estado. O padrão de estado é usado para fornecer uma maneira sistemática e com baixo acoplamento de alcançar isso por meio de implementações de contexto e estado.

Nota: Saiba mais sobre o Padrão de Estado.

8. Padrão de Visitante

O padrão de visitante é usado quando precisamos realizar uma operação em um grupo de objetos semelhantes. Com a ajuda do padrão de visitante, podemos mover a lógica operacional dos objetos para outra classe.

Nota: Saiba mais sobre o Padrão de Visitante.

9. Padrão de Intérprete

O padrão de intérprete é usado para definir uma representação gramatical de uma linguagem e fornece um intérprete para lidar com essa gramática.

10. Padrão de Iterador

O padrão de iterador é um dos padrões comportamentais e é usado para fornecer uma maneira padrão de percorrer um grupo de objetos. O padrão de iterador é amplamente utilizado no Java Collection Framework, onde a interface do iterador fornece métodos para percorrer uma Collection. Este padrão também é usado para fornecer diferentes tipos de iteradores com base em nossos requisitos. O padrão de iterador oculta a implementação real da travessia pela Collection e os programas cliente usam métodos do iterador.

Nota: Saiba mais sobre o Padrão de Iterador.

11. Padrão de Memento

O padrão de design memento é usado quando queremos salvar o estado de um objeto para que possamos restaurá-lo posteriormente. Este padrão é usado para implementar isso de tal forma que os dados de estado salvos do objeto não sejam acessíveis fora do Object, o que protege a integridade dos dados de estado salvos.

O padrão Memento é implementado com dois Objects – originator e caretaker. O originador é o Object cujo estado precisa ser salvo e restaurado, e ele usa uma classe interna para salvar o estado do Object. A classe interna é chamada de “Memento” e é private para que não possa ser acessada por outros objetos.

Padrões de Design Diversos

Há muitos padrões de design que não se enquadram nos padrões de design do Gang of Four. Vamos dar uma olhada em alguns desses padrões de design populares.

1. Padrão de Design DAO

O padrão de design Data Access Object (DAO) é usado para desacoplar a lógica de persistência de dados para uma camada separada. DAO é um padrão muito popular quando projetamos sistemas para trabalhar com bancos de dados. A ideia é manter a camada de serviço separada da camada de acesso aos dados. Dessa forma, implementamos a separação de lógica em nossa aplicação.

Nota: Saiba mais sobre o Padrão DAO.

2. Padrão de Injeção de Dependência

O padrão de injeção de dependência nos permite remover as dependências codificadas diretamente e tornar nossa aplicação com baixo acoplamento, extensível e fácil de manter. Podemos implementar a injeção de dependência em Java para mover a resolução de dependências do tempo de compilação para o tempo de execução. O framework Spring é construído com base no princípio da injeção de dependência.

Nota: Saiba mais sobre o Padrão de Injeção de Dependência.

3. Padrão MVC

O Padrão Model-View-Controller (MVC) é um dos padrões arquiteturais mais antigos para criar aplicações web.

Conclusão

Este artigo resumiu os padrões de design em Java.

Você pode conferir exemplos de código de padrões de design em Java em nosso Repositório do GitHub.

Continue seu aprendizado com mais tutoriais de Java.

Source:
https://www.digitalocean.com/community/tutorials/java-design-patterns-example-tutorial