Baixe o app para aproveitar ainda mais
Prévia do material em texto
TÉCNICAS DE PROGRAMAÇÃO Neusa Liberato Evangelista Padrões de Projeto - PARTE I Fonte: https://engsoftmoderna.info/cap6.html PADRÕES DE PROJETO Padrões de Projeto Criacionais: Factory, Singleton e Builder PARTE I Padrões de Projeto Estruturais: Proxy , Adapter, Facade e DecoratorPARTE II Padrões de Projeto Comportamentais: Strategy, Observer, Template Method, Visitor e IteratorPARTE III Fonte: Medium - Bigardi - Arquitetura e desen... https://engsoftmoderna.info/cap7.html https://gbbigardi.medium.com/arquitetura-e-desenvolvimento-de-software-parte-2-abstract-factory-f603ccc6a1ea PADRÕES DE PROJETO Em 1995, Erich Gamma, Richard Helm, Ralph Johnson e John Vlissides (Gang of Four) lançaram um livro adaptando as ideias do arquiteto Cristopher Alexander (A Patterns Language) para o mundo de desenvolvimento de software. Eles propuseram um catálogo com soluções para resolver problemas recorrentes em projeto de software, aque deram o nome de Padrões de Projeto. “Padrões de projeto descrevem objetos e classes que se relacionam para resolver um problema de projeto genérico em um contexto particular.” PADRÕES DE PROJETO Para entender os padrões propostos, precisamos entender: (1) o problema que o padrão pretende resolver; (2) o contexto em que esse problema ocorre; e (3) a solução proposta. Os quatro autores do livro de padrões de projeto defendem que devemos projetar um sistema pensando em mudanças que inevitavelmente vão ocorrer — eles chamam essa preocupação de design for change. PADRÕES DE PROJETO CRIACIONAIS: ABSTRACT FACTORY Objetivo / intenção: Permite a criação de famílias de objetos relacionados ou dependentes por meio de uma única interface e sem que a classe concreta seja especificada. Motivação: Isolar a criação de objetos de seu uso e criar famílias de objetos relacionados sem ter que depender de suas classes concretas. Permite que novos tipos derivados sejam introduzidas sem qualquer alteração ao código que usa a classe base. Aplicabilidade: Cenários onde uma família de produtos ou classes precisa ser instanciada, sem dependência de suas classes concretas. A solução consiste em duas partes: Crie interfaces padrões para os diferentes produtos dessa família. E todo o seu sistema vai trabalhar apenas com essas interfaces que você definiu. 1. Defina uma Abstract Factory, que tem os métodos de instanciação para cada uma dessas interfaces padrões definidas acima. Sempre que o sistema precisar de instâncias dos produtos ele irá conseguir as mesmas através dessa Abstract Factory. 2. PADRÕES DE PROJETO CRIACIONAIS: ABSTRACT FACTORY Suponha um sistema distribuído baseado em TCP/IP. Nesse sistema, três funções f, g e h criam objetos do tipo TCPChannel para comunicação remota. PADRÕES DE PROJETO CRIACIONAIS: ABSTRACT FACTORY Suponha que — em determinadas configurações do sistema — precisaremos usar UDP para comunicação. interface Channel { // Interface para o Channel void send(String message); } class TCPChannel implements Channel { // Implementação concreta de TCPChannel @Override public void send(String message) { System.out.println("Enviando mensagem via TCP: " + message); } } class UDPChannel implements Channel { // Implementação concreta de UDPChannel @Override public void send(String message) { System.out.println("Enviando mensagem via UDP: " + message); } } PADRÕES DE PROJETO CRIACIONAIS: SINGLE FACTORY interface ChannelFactory { // Interface para a fábrica abstrata Channel createChannel(); } class TCPChannelFactory implements ChannelFactory { // Implementação concreta da fábrica para TCPChannel @Override public Channel createChannel() { return new TCPChannel(); } } class UDPChannelFactory implements ChannelFactory { // Implementação concreta da fábrica para UDPChannel @Override public Channel createChannel() { return new UDPChannel(); } } PADRÕES DE PROJETO CRIACIONAIS: SINGLE FACTORY // Criando uma fábrica de TCPChannel ChannelFactory tcpFactory = new TCPChannelFactory(); // Criando um canal TCP Channel tcpChannel = tcpFactory.createChannel(); // Enviando mensagem através do canal TCP tcpChannel.send("Mensagem via TCP"); // Criando uma fábrica de UDPChannel ChannelFactory udpFactory = new UDPChannelFactory(); // Criando um canal UDP Channel udpChannel = udpFactory.createChannel(); // Enviando mensagem através do canal UDP udpChannel.send("Mensagem via UDP"); PADRÕES DE PROJETO CRIACIONAIS: SINGLE FACTORY Suponha que além do canal preciso criar a porta TCP ou UDP. interface Port { // Interface para a Port void open(); } class TCPPort implements Port { // Implementação concreta de TCPPort private int portNumber; public TCPPort(int portNumber) { this.portNumber = portNumber; } @Override public void open() { System.out.println("Porta TCP " + portNumber + " aberta"); } } PADRÕES DE PROJETO CRIACIONAIS: ABSTRACT FACTORY Suponha que além do canal preciso criar a porta TCP ou UDP. class UDPPort implements Port { // Implementação concreta de UDPPort private int portNumber; public UDPPort(int portNumber) { this.portNumber = portNumber; } @Override public void open() { System.out.println("Porta UDP " + portNumber + " aberta"); } } PADRÕES DE PROJETO CRIACIONAIS: ABSTRACT FACTORY Agora a Factory cria dois produtos, canal e porta do protocolo de comunicação. // Interface para a fábrica abstrata interface CommunicationFactory { Channel createChannel(); Port createPort(int portNumber); } class TCPCommunicationFactory implements CommunicationFactory { // Implementação concreta da fábrica para TCP @Override public Channel createChannel() { return new TCPChannel(); } @Override public Port createPort(int portNumber) { return new TCPPort(portNumber); } } PADRÕES DE PROJETO CRIACIONAIS: ABSTRACT FACTORY Agora a Factory cria dois produtos, canal e porta do protocolo de comunicação. class UDPCommunicationFactory implements CommunicationFactory { // Implementação concreta da fábrica para UDP @Override public Channel createChannel() { return new UDPChannel(); } @Override public Port createPort(int portNumber) { return new UDPPort(portNumber); } } PADRÕES DE PROJETO CRIACIONAIS: ABSTRACT FACTORY public class Main { public static void main(String[] args) { CommunicationFactory tcpFactory = new TCPCommunicationFactory(); // Criando uma fábrica de TCP Channel tcpChannel = tcpFactory.createChannel(); // Criando um canal TCP Port tcpPort = tcpFactory.createPort(8080); // Criando uma porta TCP com o número 8080 tcpChannel.send("Mensagem via TCP"); // Enviando mensagem através do canal TCP tcpPort.open(); // Abrindo a porta TCP CommunicationFactory udpFactory = new UDPCommunicationFactory(); // Criando uma fábrica de UDP Channel udpChannel = udpFactory.createChannel(); // Criando um canal UDP Port udpPort = udpFactory.createPort(1234); // Criando uma porta UDP com o número 1234 udpChannel.send("Mensagem via UDP"); // Enviando mensagem através do canal UDP udpPort.open(); // Abrindo a porta UDP } } PADRÕES DE PROJETO CRIACIONAIS: ABSTRACT FACTORY PADRÕES DE PROJETO CRIACIONAIS: ABSTRACT FACTORY Informar para o diagrama geral do Abstract Factory, as interfaces e classes do exemplo de Comunicação com TCP e UDP, do exemplo de uso. AbstractFactory: CommunicationFactory ConcreteFactoryX: TCPCommunicationFactory ConcreteFactoryY:UDPCommunicationFactory ProductA: Channel ProductAX: TCPChannel ProductAY: UDPChannel ProductB: Port ProductBX: TCPPort ProductBY: UDPPort PADRÕES DE PROJETO CRIACIONAIS: ABSTRACT FACTORY Vantagens: Isola as classes concretas do cliente. Facilita a troca de famílias de produtos(basta trocar uma linha de código). Promove a consistência de produtos, não há perigo de misturar objetos de famílias diferentes. Desvantagem: Dificulta a criação de produtos ligeiramente diferentes (alterar a fábrica abstrata e as concretas). PADRÕES DE PROJETO CRIACIONAIS: ABSTRACT FACTORY Exemplos de uso: Mais usado em classes estruturantes ou utilitárias. DocumentBuilder e XPathFactory em javax.xml.parsers, por exemplo. Ao criar utilitários com ou sem implementação padrão que podem ser expandidas por outras implementações. Para problemas complexos que justifiquem o uso desse padrão que é complexo e aumenta o código. PADRÕES DE PROJETO CRIACIONAIS: ABSTRACT FACTORY PADRÕES DE PROJETO CRIACIONAIS: SINGLETON Objetivo / intenção: Garantir uma única instanciação de uma classe, com um ponto de acesso único e global. Motivação: Usar para classes em que apenas uma instância de um objeto é o ideal. Aplicabilidade: Cenários em que se precisa de um único acesso global controlado ou que não existe motivo para criar várias instâncias, como um Logger ou fila de controle de requisições, por exemplo. Usos conhecidos: Criação de logs, acesso a um banco de dados ou mesmo um gerenciador de fila para fornecer itens (cliente ou outro tipo de entidade) a diferentes requisições de forma organizada e única. PADRÕES DE PROJETO CRIACIONAIS: SINGLETON A solução consiste em duas partes: Crie um um construtor default privado para evitar que seja chamada para instanciar mais de um objeto dessa classe. 1. Defina um atributo estático que armazena a instância única da classe. 2. Criar o método público e estático getInstance() (ou outro nome) que retorna essa única instância. 3. PADRÕES DE PROJETO CRIACIONAIS: SINGLETON Suponha uma classe Logger, usada para registrar as operações realizadas em um sistema. PADRÕES DE PROJETO CRIACIONAIS: SINGLETON Problema: cada método cria sua própria instância de Logger. Solução: transformar Logger em um Singleton. PADRÕES DE PROJETO CRIACIONAIS: SINGLETON Nesse novo código, temos certeza de que as três chamadas de getInstance retornam a mesma instância de Logger. PADRÕES DE PROJETO CRIACIONAIS: SINGLETON Vantagens: Economia de memória e de processamento. Garantir uma única instância de uma classe. Desvantagens: Singleton é citado como um anti padrão (antipattern) pelo fato de estar centralizando parte da aplicação dificultando a modularização e também contribuindo para aumento do acoplamento. Pode ser usado como variável global, logo criando um forte acoplamento e realizando manutenção de estado. PADRÕES DE PROJETO CRIACIONAIS: SINGLETON Exemplos de uso: Classe Runtime do java.lang. PADRÕES DE PROJETO CRIACIONAIS: SINGLETON Objetivo / intenção: Separar a lógica de construção de objetos complexos, permitindo que o processo de construção possa criar diferentes implementações. Fornecer uma maneira fácil de criar um objeto complexo, mantendo a flexibilidade. Motivação: A criação do objeto que precisa de uma quantidade de código significativa, deixa a representação um pouco extensa e difícil de manter. Portanto, criar outro tipo de objeto responsável por construir nossos objetos, isola esta complexidade de sua representação final. Aplicabilidade: Este padrão é muito utilizado para isolar a complexidade de criação de nossos objetos, criar diferentes implementações, baseadas em uma interface comum. PADRÕES DE PROJETO CRIACIONAIS: BUILDER PADRÕES DE PROJETO CRIACIONAIS: BUILDER Director: Constrói um objeto utilizando a interface do builder; Builder: Especifica uma interface para um construtor de partes do objeto- produto; ConcreteBuilder: Define uma implementação da interface builder, mantém a representação que cria e fornece interface para recuperação do produto; Product: O objeto complexo construído. Inclui classes que definem as partes constituintes. PADRÕES DE PROJETO CRIACIONAIS: BUILDER Vantagens: Encapsular o processo de criação, facilitando a modificação e manutenção do código. Permitir a criação de objetos complexos com um processo de construção flexível. Separar o processo de construção do código do cliente, facilitando o gerenciamento. Desvantagens: Adicionar complexidade, tornando-a mais difícil de entender. Pode levar à criação de múltiplas classes de construtores, que podem ser difíceis de gerenciar. Pode não ser adequado para aplicações menores ou objetos com construções simples. PADRÕES DE PROJETO CRIACIONAIS: BUILDER PADRÕES DE PROJETO CRIACIONAIS: BUILDER public class Pessoa { private Long id; private String nome; private String telefone; private String numeroDocumento; private TipoDocumento tipoDocumento; private LocalDate dataNascimento; // Construtor privado para forçar o uso do Builder private Pessoa(Builder builder) { this.id = builder.id; this.nome = builder.nome; this.telefone = builder.telefone; this.numeroDocumento = builder.numeroDocumento; this.tipoDocumento = builder.tipoDocumento; this.dataNascimento = builder.dataNascimento; } PADRÕES DE PROJETO CRIACIONAIS: BUILDER // Métodos getters para os atributos ... // Builder estático interno à classe Pessoa public static class Builder { private Long id; private String nome; private String telefone; private String numeroDocumento; private TipoDocumento tipoDocumento; private LocalDate dataNascimento; public Builder id(Long id) { this.id = id; return this; } PADRÕES DE PROJETO CRIACIONAIS: BUILDER public Builder nome(String nome) { this.nome = nome; return this; } public Builder telefone(String telefone) { this.telefone = telefone; return this; } public Builder numeroDocumento(String numeroDocumento) { this.numeroDocumento = numeroDocumento; return this; } PADRÕES DE PROJETO CRIACIONAIS: BUILDER public Builder tipoDocumento(TipoDocumento tipoDocumento) { this.tipoDocumento = tipoDocumento; return this; } public Builder dataNascimento(LocalDate dataNascimento) { this.dataNascimento = dataNascimento; return this; } // Método para construir instância de Pessoa com atributos configurados no Builder public Pessoa build() { return new Pessoa(this); } } } StringBuilder builder = new StringBuilder(); builder.append("Hello"); builder.append(" "); builder.append("World"); String result = builder.toString(); @Builder public class Pessoa { private String nome; private int idade; } Exemplos de uso: Classe StringBuilder e StringBuffer (para construir strings de maneira eficiente, especialmente quando se precisa concatenar várias strings). A biblioteca Lombok fornece uma anotação @Builder para gerar automaticamente um padrão Builder para uma classe. PADRÕES DE PROJETO CRIACIONAIS: BUILDER OBRIGADA Neusa Liberato Evangelista
Compartilhar