




























































































Estude fácil! Tem muito documento disponível na Docsity
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Prepare-se para as provas
Estude fácil! Tem muito documento disponível na Docsity
Prepare-se para as provas com trabalhos de outros alunos como você, aqui na Docsity
Encontra documentos específicos para os exames da tua universidade
Prepare-se com as videoaulas e exercícios resolvidos criados a partir da grade da sua Universidade
Responda perguntas de provas passadas e avalie sua preparação.
Ganhe pontos para baixar
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Apostila de Design Patterns Em Java
Tipologia: Notas de estudo
1 / 125
Esta página não é visível na pré-visualização
Não perca as partes importantes!





























































































Design Patterns em Java
- 5 de janeiro de Sobre a K
A K19 é uma empresa especializada na capacitação de desenvolvedores de software. Sua equipe
é composta por profissionais formados em Ciência da Computação pela Universidade de São Paulo
(USP) e que possuem vasta experiência em treinamento de profissionais para área de TI.
O principal objetivo da K19 é oferecer treinamentos de máxima qualidade que relacionados às
principais tecnologias utilizadas pelas empresas. Através desses treinamentos, seus alunos se tornam
capacitados para atuar no mercado de trabalho.
Visando a máxima qualidade, a K19 mantém as suas apostilas em constante renovação e melho-
ria, oferece instalações físicas apropriadas para o ensino e seus instrutores estão sempre atualizados
didática e tecnicamente.
Termo de Uso
Termo de Uso
Todo o conteúdo desta apostila é propriedade da K19 Treinamentos. A apostila pode ser utilizada
livremente para estudo pessoal. Além disso, este material didático pode ser utilizado como material
de apoio em cursos de ensino superior desde que a instituição correspondente seja reconhecida pelo
MEC (Ministério da Educação) e que a K19 seja citada explicitamente como proprietária do material.
É proibida qualquer utilização desse material que não se enquadre nas condições acima sem
o prévio consentimento formal, por escrito, da K19 Treinamentos. O uso indevido está sujeito às
medidas legais cabíveis.
K01- Lógica de Programação
K11 - Orientação a Objetos em Java
K12 - Desenvolvimento Web com JSF2 e JPA
K21 - Persistência com JPA2 e Hibernate
K22 - Desenvolvimento Web Avançado com JFS2, EJB3.1 e CDI
K23 - Integração de Sistemas com Webservices, JMS e EJB
K31 - C# e Orientação a Objetos
K32 - Desenvolvimento Web com ASP.NET MVC
TREINAMENTOSTREINAMENTOSTREINAMENTOS Conheça os nossos cursos
www.k19.com.br/cursos
Para não perder tempo e dinheiro elaborando soluções diferentes para o mesmo problema, po-
deríamos escolher uma solução como padrão e adotá-la toda vez que o problema correspondente
ocorrer. Além de evitar o retrabalho, facilitaríamos a comunicação dos desenvolvedores e o entendi-
mento técnico do sistema.
Daí surge o conceito de padrão de projeto ou design pattern. Um padrão de projeto é uma
solução consolidada para um problema recorrente no desenvolvimento e manutenção de software
orientado a objetos.
A referência mais importante relacionada a padrões de projeto é o livro Design Patterns: Elements
of Reusable Object-Oriented Software (editora Addison-Wesley, 1995) dos autores Erich Gamma, Ri-
chard Helm, Ralph Johnson e John Vlissides. Esses quatro autores são conhecidos como “Gang of
Four”(GoF). Os diagramas UML apresentados nesta apostila são baseados nos diagramas desse livro.
Padrões GoF
Os padrões definidos no livro Design Patterns: Elements of Reusable Object-Oriented Software são
denominados padrões GoF. Eles são classificados em três categorias: padrões de criação , estruturais
e comportamentais.
PADRÕES DE CRIAÇÃO
C
Em um sistema orientado a objetos, a criação de certos objetos pode ser uma tarefa extrema-
mente complexa. Podemos destacar dois problemas relacionados a criação de objetos:
Seguindo o princípio do encapsulamento, essa complexidade deve ser isolada. A seguir, mostra-
remos padrões de projetos que podem ser adotados para encapsular a criação de objetos em diversas
situações distintas.
Veja abaixo um resumo do objetivo de cada padrão de criação.
Factory Method Encapsular a escolha da classe concreta a ser utilizada na criação de objetos de um
determinado tipo.
Abstract Factory Encapsular a escolha das classes concretas a serem utilizadas na criação dos obje-
tos de diversas famílias.
Builder Separar o processo de construção de um objeto de sua representação e permitir a sua cri-
ação passo-a-passo. Diferentes tipos de objetos podem ser criados com implementações dis- tintas de cada passo.
Prototype Possibilitar a criação de novos objetos a partir da cópia de objetos existentes.
Singleton Permitir a criação de uma única instância de uma classe e fornecer um modo para recuperá-
la.
Multiton Permitir a criação de uma quantidade limitada de instâncias de determinada classe e for-
necer um modo para recuperá-las.
Object Pool Possibilitar o reaproveitamento de objetos.
Factory Method
Objetivo: Encapsular a escolha da classe concreta a ser utilizada na criação de objetos de um de-
terminado tipo.
1 public class EmissorJMS implements Emissor { 2 public void envia ( String mensagem ) { 3 System. out. println (" Enviando por JMS a mensagem : "); 4 System. out. println ( mensagem ); 5 } 6 }
Código Java 2.4: EmissorJMS.java
Quando for necessário enviar um mensagem, podemos utilizar diretamente esses emissores.
1 Emissor emissor = new EmissorSMS () ; 2 emissor. envia (" K19 - Treinamentos ");
Código Java 2.5: Enviando uma mensagem por SMS
1 Emissor emissor = new EmissorEmail () ; 2 emissor. envia (" K19 - Treinamentos ");
Código Java 2.6: Enviando uma mensagem por email
1 Emissor emissor = new EmissorJMS () ; 2 emissor. envia (" K19 - Treinamentos ");
Código Java 2.7: Enviando uma mensagem por JMS
Utilizando essa abordagem, o código que deseja enviar uma mensagem referencia diretamente
as classes que implementam os mecanismos de envio. Para eliminar essa referência direta, podemos
adicionar um intermediário entre o código que deseja enviar uma mensagem e as classes que imple-
mentam os emissores. Esse intermediário será o responsável pela escolha da classe concreta a ser
utilizada para criar o tipo de emissor adequado.
1 public class EmissorCreator { 2 public static final int SMS = 0; 3 public static final int EMAIL = 1; 4 public static final int JMS = 2; 5 6 public Emissor create ( int tipoDeEmissor ) { 7 if ( tipoDeEmissor == EmissorCreator. SMS ) { 8 return new EmissorSMS () ; 9 } else if ( tipoDeEmissor == EmissorCreator. EMAIL ) { 10 return new EmissorEmail () ; 11 } else if ( tipoDeEmissor == EmissorCreator. JMS ) { 12 return new EmissorJMS () ; 13 } else { 14 throw new IllegalArgumentException (" Tipo de emissor não suportado "); 15 } 16 } 17 }
Código Java 2.8: EmissorCreator.java
Especialização
Talvez, o sistema tenha que trabalhar com dois tipos diferentes de envio de mensagens: síncrono
e assíncrono. Podemos especializar o criador de emissores, definindo subclasses.
1 public class EmissorAssincronoCreator extends EmissorCreator { 2 public Emissor create ( int tipoDeEmissor ) { 3 if ( tipoDeEmissor == EmissorCreator. SMS ) { 4 return new EmissorAssincronoSMS () ; 5 } else if ( tipoDeEmissor == EmissorCreator. EMAIL ) { 6 return new EmissorAssincronoEmail () ; 7 } else if ( tipoDeEmissor == EmissorCreator. JMS ) { 8 return new EmissorAssincronoJMS () ; 9 } else { 10 throw new IllegalArgumentException (" Tipo de emissor não suportado "); 11 } 12 } 13 }
Código Java 2.9: EmissorAssincronoCreator.java
1 public class EmissorSincronoCreator extends EmissorCreator { 2 public Emissor create ( int tipoDeEmissor ) { 3 if ( tipoDeEmissor == EmissorCreator. SMS ) { 4 return new EmissorSincronoSMS () ; 5 } else if ( tipoDeEmissor == EmissorCreator. EMAIL ) { 6 return new EmissorSincronoEmail () ; 7 } else if ( tipoDeEmissor == EmissorCreator. JMS ) { 8 return new EmissorSincronoJMS () ; 9 } else { 10 throw new IllegalArgumentException (" Tipo de emissor não suportado "); 11 } 12 } 13 }
Código Java 2.10: EmissorSincronoCreator.java
Agora, para enviar uma mensagem, podemos acionar o criador adequado (EmissorCreator,
EmissorAssincronoCreator ou EmissorSincronoCreator) para obter o emissor desejado.
1 EmissorCreator creator = new EmissorAssincronoCreator () ; 2 Emissor emissor = creator. create ( EmissorCreator. SMS ) 3 emissor. envia (" K19 - Treinamentos ");
Código Java 2.11: Enviando uma mensagem por SMS
1 EmissorCreator creator = new EmissorAssincronoCreator () ; 2 Emissor emissor = creator. create ( EmissorCreator. EMAIL ) 3 emissor. envia (" K19 - Treinamentos ");
Código Java 2.12: Enviando uma mensagem por email
1 EmissorCreator creator = new EmissorSincronoCreator () ; 2 Emissor emissor = creator. create ( EmissorCreator. JMS ) 3 emissor. envia (" K19 - Treinamentos ");
Código Java 2.13: Enviando uma mensagem por JMS
Organização
O diagrama UML abaixo ilustra a organização desse padrão.
Código Java 2.15: EmissorSMS.java
1 public class EmissorEmail implements Emissor { 2 public void envia ( String message ) { 3 System. out. println (" Enviando por email a mensagem : "); 4 System. out. println ( message ); 5 } 6 }
Código Java 2.16: EmissorEmail.java
1 public class EmissorJMS implements Emissor { 2 public void envia ( String message ) { 3 System. out. println (" Enviando por JMS a mensagem : "); 4 System. out. println ( message ); 5 } 6 }
Código Java 2.17: EmissorJMS.java
(^4) Crie uma classe para testar os emissores.
1 public class TestaEmissores { 2 public static void main ( String [] args ) { 3 Emissor emissor1 = new EmissorSMS () ; 4 emissor1. envia (" K19 Treinamentos "); 5 6 Emissor emissor2 = new EmissorEmail () ; 7 emissor2. envia (" K19 Treinamentos "); 8 9 Emissor emissor3 = new EmissorJMS () ; 10 emissor3. envia (" K19 Treinamentos "); 11 } 12 }
Código Java 2.18: TestaEmissores.java
(^5) Para tornar a classe TestaEmissores menos dependente das classes que implementam os me-
canismos de envio, podemos definir uma classe intermediária que será responsável pela criação dos
emissores.
1 public class EmissorCreator { 2 public static final int SMS = 0; 3 public static final int EMAIL = 1; 4 public static final int JMS = 2; 5 6 public Emissor create ( int tipoDeEmissor ) { 7 if ( tipoDeEmissor == EmissorCreator. SMS ) { 8 return new EmissorSMS () ; 9 } else if ( tipoDeEmissor == EmissorCreator. EMAIL ) { 10 return new EmissorEmail () ; 11 } else if ( tipoDeEmissor == EmissorCreator. JMS ) { 12 return new EmissorJMS () ; 13 } else { 14 throw new IllegalArgumentException (" Tipo de emissor não suportado "); 15 } 16 } 17 }
Código Java 2.19: EmissorCreator.java
(^6) Altere a classe TestaEmissores para utilizar a classe EmissorCreator.
1 public class TestaEmissores { 2 public static void main ( String [] args ) { 3 EmissorCreator creator = new EmissorCreator () ; 4 5 // SMS 6 Emissor emissor1 = creator. create ( EmissorCreator. SMS ); 7 emissor1. envia (" K19 Treinamentos "); 8 9 // Email 10 Emissor emissor2 = creator. create ( EmissorCreator. EMAIL ); 11 emissor2. envia (" K19 Treinamentos "); 12 13 // JMS 14 Emissor emissor3 = creator. create ( EmissorCreator. JMS ); 15 emissor3. envia (" K19 Treinamentos "); 16 } 17 }
Código Java 2.20: TestaEmissores.java
Abstract Factory
Objetivo: Encapsular a escolha das classes concretas a serem utilizadas na criação dos objetos de
diversas famílias.
Exemplo prático
Estabelecimentos comerciais normalmente oferecem aos clientes diversas opções de pagamento.
Por exemplo, clientes podem efetuar pagamentos com dinheiro, cheque, cartões de crédito ou dé-
bito, entre outros.
Pagamentos com cartões são realizados por meio de uma máquina de cartão, oferecida e insta-
lada por empresas como Cielo e Redecard. Geralmente, essa máquina é capaz de lidar com cartões
de diferentes bandeiras (como Visa e Mastercard).
Nosso objetivo é programar essas máquinas, isto é, desenvolver uma aplicação capaz de se co-
municar com as diferentes bandeiras e registrar pagamentos.
No momento do pagamento, a máquina de cartão deve enviar as informações relativas a transa-
ção (como valor e senha) para a bandeira correspondente ao cartão utilizado. Além disso, a máquina
deve aguardar uma resposta de confirmação ou recusa do pagamento.
1 public class VisaComunicadorFactory implements ComunicadorFactory { 2 public Emissor createEmissor () { 3 // criando um emissor Visa 4 } 5 6 public Receptor createReceptor () { 7 // criando um receptor Visa 8 } 9 }
Código Java 2.22: VisaComunicadorFactory.java
1 public class MastercardComunicadorFactory implements ComunicadorFactory { 2 public Emissor createEmissor () { 3 // criando um emissor Mastercard 4 } 5 6 public Receptor createReceptor () { 7 // criando um receptor Mastercard 8 } 9 }
Código Java 2.23: MastercardComunicadorFactory.java
O processo de escolha da fábrica é realizado de acordo com a bandeira do cartão utilizado.
1 public ComunicadorFactory getComunicadorFactory ( Cartao cartao ) { 2 String bandeira = cartao. getBandeira () ; 3 Class clazz = Class. forName ( bandeira + " ComunicadorFactory "); 4 return ( ComunicadorFactory ) clazz. newInstance () ; 5 }
Código Java 2.24: Selecionando a fábrica de acordo com as preferências do usuário
Dessa forma, o código da aplicação se torna independente da fábrica utiliza.
1 Cartao cartao = ... 2 ComunicadorFactory factory = getComunicadorFactory ( cartao ); 3 4 String transacao = ... 5 Emissor emissor = factory. getEmissor () ; 6 emissor. envia ( transacao ); 7 8 Receptor receptor = factory. getReceptor () ; 9 String resposta = receptor. recebe () ;
Código Java 2.25: enviando mensagens
Organização
O diagrama UML abaixo ilustra a organização desse padrão.
AbstractFactory createProductA() createProductB()
ConcreteFactory createProductA() createProductB()
ConcreteFactory createProductA() createProductB()
AbstractProductA
ConcreteProductA1 ConcreteProductA
AbstractProductB
ConcreteProductB1 ConcreteProductB
Client
<
<
<
<
<
Figura 2.4: UML do padrão Abstract Factory
Os personagens desse padrão são:
AbstractFactory (ComunicadorFactory)
Interface que define as assinaturas dos métodos responsáveis pela criação dos objetos uma família.
ConcreteFactory (VisaComunicadorFactory, MastercardComunicadorFactory)
Classe que implementa os métodos de criação dos objetos de uma família.
AbstractProduct (Emissor, Receptor)
Interface que define um tipo de produto.
ConcreteProduct (EmissorVisa, ReceptorVisa, EmissorMastercard, ReceptorMastercard)
Implementação particular de um tipo de produto.
Client (Aplicação)
Usa apenas as interfaces AbstractFactory e AbstractProduct.
Abstract Factory + Factory Method
Podemos combinar os dois padrões vistos anteriormente. As implementações da Abstract Fac-
tory podem acionar os Factory Methods para criar os emissores e receptores.
1 public class VisaComunicadorFactory implements ComunicadorFactory { 2 private EmissorCreator emissorCreator = new EmissorCreator () ; 3 private ReceptorCreator receptorCreator = new ReceptorCreator () ; 4 5 public Emissor createEmissor () { 6 return this. emissorCreator. create ( EmissorCreator. VISA ); 7 } 8 9 public Receptor createReceptor () { 10 return this. receptorCreator. create ( ReceptorCreator. VISA ); 11 }