Upload
others
View
0
Download
0
Embed Size (px)
Citation preview
Técnicas de Projeto e Implementação de Sistemas I
Prof.: Diego [email protected]
Conteúdo: Padrões Adapter & Facade
Baseado nos slides originais cedidos pelo Prof. Anselmo Montenegro.Documento baseado no material preparado peloProf. Luiz André (http://www.ic.uff.br/~lapaesleme/)
10/11/2014 Técnicas de Programação Avançada 2
Padrões de Projeto
Como fazer a interface de um objeto parecer o que ela de fato não é?
Como adaptar um projeto que espera uma interface para uma classe que implementa uma interface distinta?
Como encapsular objetos com o intuito de simplificar suas interfaces?
Introdução
10/11/2014 Técnicas de Programação Avançada 3
Padrões de Projeto
Suponha que um dado sistema precise de um componente do tipo Peg (cavilha).
Este componente tem um único comportamento: ser inserido em uma outra peça para fornecer sustentação.
Um Primeiro Exemplo
10/11/2014 Técnicas de Programação Avançada 4
Padrões de Projeto
Inicialmente, trabalhávamos com uma implementação de cavilha chamada SquarePeg (cavilha quadrada).
Ela possuia a seguinte interface:
Um primeiro exemplo
public class SquarePeg {public void insert(String str) {System.out.println("SquarePeg insert(): " + str);
}}
10/11/2014 Técnicas de Programação Avançada 5
Padrões de Projeto
Entretanto, em dado momento, fomos forçados a usar uma implementação alternativa: RoundPeg.
Uma RoundPeg faz a mesma coisa que uma SquarePeg, mas com interface diferente.
O método insert(), neste caso, se chama insertIntoHole().
Um primeiro exemplo
public class RoundPeg {public void insertIntoHole(String msg) {System.out.println("RoundPeg insertIntoHole(): " + msg);
}}
10/11/2014 Técnicas de Programação Avançada 6
Padrões de Projeto
O cliente (nosso sistema) somente entende a interface de SquarePeg, com o método insert(String str).
Mas temos agora que usar RoundPeg.
Como podemos utilizar esta implementação alternativa sem alterar o código do cliente?
Solução: adaptação de interface.
Um primeiro exemplo
10/11/2014 Técnicas de Programação Avançada 7
Padrões de Projeto
Mais genericamente, considere um sistema de software que funciona bem utilizando uma API fornecida por um vendedor
O Problema de adaptação de interfaces
APIantiga
SistemaSistema
Em um determinado momento, o sistema precisa trabalhar com uma API semelhante, fornecida por um novo vendedor, que não implementa as interfaces esperadas pelo sistema
10/11/2014 Técnicas de Programação Avançada 8
Padrões de ProjetoO Problema de adaptação de interfaces
NovaAPI
SistemaSistema
Sistema não deve ser modificado
As classes da nova API também não podem ser modificadas
Como resolver tal problema?
10/11/2014 Técnicas de Programação Avançada 9
Padrões de ProjetoO Problema de adaptação de interfaces
NovaAPI
SistemaSistema
Iremos criar uma classe adaptador que adapte a interface da nova API para a interface esperada pelo sistema
10/11/2014 Técnicas de Programação Avançada 10
Padrões de ProjetoO Problema de adaptação de interfaces
NovaAPI
AdapterSistemaSistema
10/11/2014 Técnicas de Programação Avançada 11
Padrões de Projeto
O Adaptador funciona como um meio de campo, obtendo as requisições do cliente e traduzindo tais requisições para um formato esperado pela classe do vendedor
O Problema de adaptação de interfaces
NovaAPI
AdapterSistemaSistema
10/11/2014 Técnicas de Programação Avançada 12
Padrões de ProjetoMetáfora do Adaptador
Cliente AdapterVendor
API
10/11/2014 Técnicas de Programação Avançada 13
Padrões de Projeto
O Padrão Adapter converte a interface de uma classe em uma outra interface esperada pelo cliente. O adaptador permite que classes com interfaces originalmente incompatíveis possam trabalhar em conjunto.
O Padrão Adapter
10/11/2014 Técnicas de Programação Avançada 14
Padrões de ProjetoSolução usando o Padrão Adapter
Vamos tentar aplicar este conceito ao problema das cavilhas.
Relembrando: o sistema usa a interface para SquarePeg, mas precisamos usar a implementação RoundPeg.
Logo, nosso adaptador precisa disponibilizar a interface SquarePeg e “traduzir” as chamadas do cliente para a implementação de RoundPeg.
Vamos utilizar o conceito de delegação: nosso adaptador terá uma instância de RoundPeg e delegará os comportamentos.
10/11/2014 Técnicas de Programação Avançada 15
Padrões de ProjetoSolução usando o Padrão Adapter
public class PegAdapter extends SquarePeg {private RoundPeg roundPeg;public PegAdapter() {this.roundPeg = new RoundPeg();}public void insert(String str) {roundPeg.insertIntoHole(str);}
}
public class TestPegs {public static void main(String args[]) {// Create some pegs.SquarePeg squarePeg = new PegAdapter();// Do an insert using the square peg.squarePeg.insert("Inserting square peg...");
}
10/11/2014 Técnicas de Programação Avançada 16
Padrões de ProjetoSolução usando o Padrão Adapter
Note que nesta solução, o uso da classe RoundPeg é completamente transparente para o cliente (classe TestPeg).
Como Adapter é um subtipo de SquarePeg, cliente continua usando a mesma interface.
De fato, o cliente sequer precisa saber que a classe RoundPeg existe.
O mais comum, no entanto, é usarmos o padrão Adapter de forma um pouco menos transparente. Cliente sabe que utilizará um RoundPeg, mas pede explicitamente ao adaptador que faça a adaptação.
10/11/2014 Técnicas de Programação Avançada 17
Padrões de ProjetoSolução usando o Padrão Adapter
public class PegAdapter extends SquarePeg {private RoundPeg roundPeg;public PegAdapter(RoundPeg peg) {this.roundPeg = peg;}public void insert(String str) {roundPeg.insertIntoHole(str);}
}
public class TestPegs {public static void main(String args[]) {// Create some pegs.RoundPeg roundPeg = new RoundPeg();SquarePeg squarePeg = new PegAdapter(roundPeg);// Do an insert using the square peg.squarePeg.insert("Inserting square peg...");
}
10/11/2014 Técnicas de Programação Avançada 18
Padrões de ProjetoSolução usando o Padrão Adapter
Neste caso, cliente é obrigado a conhecer a classe RoundPeg e, inclusive, instanciá-la.
Desta forma, migrar de SquarePeg para RoundPeg exigiria uma ligeira alteração no código do cliente.
Ele precisa alterar o tipo da variável declarada (de RoundPeg para PegAdapter) e precisa instanciar uma SquarePeg.
Mas a modificação é pequena: deste ponto em diante, toda a manipulação permanece igual.
10/11/2014 Técnicas de Programação Avançada 19
Padrões de ProjetoAdaptador Bidirecional
Note que podemos fazer um adaptador “bidirecional”.
Isto é, uma mesma classe adaptador que permita adaptar de RoundPeg para SquarePeg e de SquarePeg para RoundPeg.
Para isso, basta fazer o adaptador implementar ambas as interfaces e manter referências para dois objetos, um de cada tipo.
10/11/2014 Técnicas de Programação Avançada 20
Padrões de ProjetoAdaptador Bidirecional
public interface IRoundPeg {public void insertIntoHole(String msg);
}
public interface ISquarePeg {public void insert(String str);
}
10/11/2014 Técnicas de Programação Avançada 21
Padrões de ProjetoAdaptador Bidirecional
public class PegAdapter implements ISquarePeg, IRoundPeg {
private RoundPeg roundPeg;private SquarePeg squarePeg;
public PegAdapter(RoundPeg peg) {this.roundPeg = peg;}public PegAdapter(SquarePeg peg) {this.squarePeg = peg;}public void insert(String str) {roundPeg.insertIntoHole(str);}public void insertIntoHole(String msg){squarePeg.insert(msg);}
}
10/11/2014 Técnicas de Programação Avançada 22
Padrões de ProjetoUm segundo exemplo
public class TestPegs {
public static void main(String args[]) {// Create some pegs.RoundPeg roundPeg = new RoundPeg();SquarePeg squarePeg = new SquarePeg();
// Do an insert using the square peg.squarePeg.insert("Inserting square peg...");// Create a two-way adapter and do an insert with it.ISquarePeg roundToSquare = new PegAdapter(roundPeg);roundToSquare.insert("Inserting round peg...");// Do an insert using the round peg.roundPeg.insertIntoHole("Inserting round peg...");// Create a two-way adapter and do an insert with it.IRoundPeg squareToRound = new PegAdapter(squarePeg);squareToRound.insertIntoHole("Inserting square peg...");}
}
10/11/2014 Técnicas de Programação Avançada 23
Padrões de ProjetoUm segundo exemplo
Suponha agora uma versão mais complexa do problema.
Nosso sistema deve suportar utilizar tanto a implementação SquarePeg, quanto a RoundPeg.
Para complicar, integramos código de algumas classes/módulos que, ao contrário do nosso sistema original, utilizavam a interface de RoundPeg.
Mas ambos precisam gerenciar a mesma cavilha (mesma instância).
10/11/2014 Técnicas de Programação Avançada 24
Padrões de ProjetoUm segundo exemplo
10/11/2014 Técnicas de Programação Avançada 25
Padrões de ProjetoUm segundo exemplo
10/11/2014 Técnicas de Programação Avançada 26
Padrões de ProjetoUm segundo exemplo
De alguma forma, este objeto único acessado por ambas as classes do sistema original e dos módulos adicionados precisa responder por duas interfaces ao mesmo tempo.
Como fazer isso?
Solução: parecida com um “adaptador bidirecional”, mas com algumas verificações adicionais.
10/11/2014 Técnicas de Programação Avançada 27
Padrões de ProjetoUm segundo exemplo
public interface IRoundPeg {public void insertIntoHole(String msg);
}
public interface ISquarePeg {public void insert(String str);
}
10/11/2014 Técnicas de Programação Avançada 28
Padrões de ProjetoUm segundo exemplo
public class PegAdapter implements ISquarePeg, IRoundPeg {
private RoundPeg roundPeg = null;private SquarePeg squarePeg = null;
public PegAdapter(RoundPeg peg) {this.roundPeg = peg;}public PegAdapter(SquarePeg peg) {this.squarePeg = peg;}public void insert(String str) {
if (roundPeg != null) roundPeg.insertIntoHole(str);else squarePeg.insert(str);
}public void insertIntoHole(String msg){
if (squarePeg != null) squarePeg.insert(msg);else roundPeg.insertIntoHole(msg)
}}
10/11/2014 Técnicas de Programação Avançada 29
Padrões de ProjetoO Padrão Adapter
De forma mais genérica, o padrão Adapter pode ser implementado de duas formas:
• O padrão adapter para classes.• O padrão adapter para objetos.
Na versão para objetos, a classe Adaptador herda (ou implementa) a interface que desajamos usar e contém uma referência para uma instância da classe a ser adaptada (cuja interface não conhecemos).
Implementação apresentada para o primeiro exemplo: utiliza o conceito de delegação.
10/11/2014 Técnicas de Programação Avançada 30
Padrões de ProjetoO Padrão Adapter – Diagrama de Classes
10/11/2014 Técnicas de Programação Avançada 31
Padrões de ProjetoO Padrão Adapter
A versão para classes é um pouco diferente.
A classe adaptador passa a herdar da classe a ser adaptada (passa a ser um subtipo dela).
Mas, ao mesmo tempo, a classe adaptador implementa a interface que desejamos disponibilizar.
A execução dos comportamentos não é mais feita por delegação.
Ao invés disso, estes comportamentos são herdados.
10/11/2014 Técnicas de Programação Avançada 32
Padrões de ProjetoO Padrão Adapter (versão Class Adapter)–
Diagrama de Classes
10/11/2014 Técnicas de Programação Avançada 33
Padrões de ProjetoUtilização do Padrão Adapter
Utilização
Quando se quiser utilizar uma classe existente, mas sua interface não é adequada.
Quando se deseja criar e reutilizar uma classe para interoperar com classes ainda não existentes
Quando se deseja utilizar classes e é impraticável criar inúmeras subclasses.
10/11/2014 Técnicas de Programação Avançada 34
Padrões de ProjetoO Padrão Adapter
Participantes
Alvo – define a interface utilizada pelo cliente
Cliente – utiliza os objetos com a interface alvo.
Adaptado – define a interface que se quer “modificar”
Adaptador – define a interface que será mapeada para a interface do adaptado.
10/11/2014 Técnicas de Programação Avançada 35
Padrões de ProjetoExercício (Adaptado do Material de Bob Tarr)
Suponha que tenhamos uma classe VectorUtilities que provê um método estático copy:
O método gera uma cópia de um Vector para outro, mas apenas com elementos que sejam “copiáveis”. O método supõe que os elementos do Vector implementam uma interface chamada Copyable.
public static Vector copy(Vector vin) {
Vector vout = new Vector();
Enumeration e = vin.elements();
while (e.hasMoreElements()) {
Copyable c = (Copyable) e.nextElement();
if (c.isCopyable()) vout.addElemet(c);
}
return vout;
}
10/11/2014 Técnicas de Programação Avançada 36
Padrões de ProjetoExercício (Adaptado do Material de Bob Tarr)
A interface Copyable define um único método, chamado isCopyable() (retorna um booleano).
Suponha agora que tenhamos uma classe Document que não implementa Copyable. Mas desejamos aplicar o método copy() sobre um Vector de Document.
A classe Document tem um método chamado isValid() e queremos que apenas os documentos válidos sejam copiados.
Escreva uma classe Adaptador que possa ser usada para resolver o problema sem alterar a classe Document.
10/11/2014 Técnicas de Programação Avançada 37
Padrões de ProjetoPadrão Facade
Fachada de la iglesia de la Compañía de Jesús en Segovia
http://commons.wikimedia.org/wiki/File:IGLESIA_COMPA%C3%91IA_FACHADA_ALZADO.jpg
10/11/2014 Técnicas de Programação Avançada 38
Padrões de ProjetoPadrão Facade
Como lidar com um sistema que depende de um subsistema muito complexo?
Como limitar a dependência do cliente principal em relação às classes do subsistema?
Como combinar as interfaces das classes no subsistema para prover um interface simplificada, com uma funcionalidade específica e delimitada?
10/11/2014 Técnicas de Programação Avançada 39
Padrões de ProjetoExemplo de problema
Suponha um sistema que controla os vários dispositivos que fazem parte de um HomeTheather.
Há leitores de CD/DVD/Blu-Ray, Amplificadores, Projetores, Iluminação...
10/11/2014 Técnicas de Programação Avançada 40
Padrões de ProjetoExemplo de problema
PopcornPopper
on()off()pop()
TheaterLights
on()off()dim()
Screen
up( )down()
CdPlayer
amplifier
on()
off()eject()pause()
play()play()stop()
Amplifier
turnerdvdPlayercdPlayer
on()off()
setCd()setDvd()setStereoSound()
setSurroundSoud()setTuner()setVolume()
DvdPlayer
amplifier
on()
off()eject() pause()
play() setSurroundAudio() setTwoChannelAudio()
stop()
Projector
dvdPlayer
on()
off()tvMode()wideScreenMode()
Turner
amplifier
on()
off()setAm()setFm()
setFrequency()
10/11/2014 Técnicas de Programação Avançada 41
Padrões de ProjetoExemplo de problema
Passos para assistir um filme usando o HomeTheater
1. Ligar a pipoqueira ( popcornPopper.on( ) )2. Iniciar a preparação das pipocas ( popcornPopper.pop( ) )3. Diminuir as luzes ( theaterLights.dim( ) )4. Baixar a tela ( screen.down( ) )5. Ligar o projetor (projector.on( ) )6. Vincular a entrada do projetor ao Dvd (projector.tvMode( ) )7. Colocar o projetor no modo wide-screen (project.wideScreenMode( ) )8. Ligar o amplificador de som ( amplifier.on( ) )9. Configurar a entrada do amplificador para o DVD ( amplifier.setDvd( ) )10. Configurar o amplificador para surround sound ( amplifier.setSurroundSound() ) )11. Configurar o volume do amplificador para médio ( amplifier.setSound( ) )12. Ligar o DVD Player ( dvd.on( ) )13. Iniciar o filme (dvd.play( ) )
10/11/2014 Técnicas de Programação Avançada 42
Padrões de ProjetoExemplo de problema
public class HomeTheaterTestDrive {
public static void main(String[] args) {
// instantiate components here
popcornPopper.on( );
popcornPopper.pop( ) ;
theaterLights.dim( ) ;
screen.down( ) ;
projector.on( ) ;
projector.tvMode( );
project.wideScreenMode( ) ;
amplifier.on( ) ;
amplifier.setDvd( ) ;
amplifier.setSurroundSound() ;
amplifier.setSound( ) ;
dvd.on( );
dvd.play(“Raiders of the Lost Ark”) ;
}
}
10/11/2014 Técnicas de Programação Avançada 43
Padrões de Projeto
Neste exemplo, o cliente (classe HomeTheaterTestDrive) precisaconhecer as várias classes que compõem o HomeTheather.
O cliente precisa ainda saber a exata ordem em que os métodosdestas classes precisam ser chamados.
E os argumentos que devem ser passados.
O cliente tem muito controle sobre a configuração do HomeTheather, mas ao mesmo tempo tem muito trabalho paraconfigurá-lo.
O Princípio do Conhecimento Mínimo
10/11/2014 Técnicas de Programação Avançada 44
Padrões de Projeto
Princípio do conhecimento mínimo – interaja apenas com seus amigos mais próximos.
O Princípio do Conhecimento Mínimo
10/11/2014 Técnicas de Programação Avançada 45
Padrões de Projeto
Qual o significado do princípio do conhecimento
mínimo?
Significa que, em um projeto, deve-se ter cuidado com o número de
classes que interagem com um dado objeto e como ele interage com
tais classes
O princípio evita o projeto de classes acopladas a um grande número
de outras classes
O Princípio do Conhecimento Mínimo
10/11/2014 Técnicas de Programação Avançada 46
Padrões de ProjetoDe Volta ao Exemplo Inicial
Qual a dificuldade em controlar todos esses dispositivos para realizar a tarefa desejada?
• Aplicação ou objeto cliente depende de muitas classes diferentes
• As classes utilizadas possuem interfaces mais complexas do que o necessário para a tarefa a ser realizada
• Se o subsistema for modificado, os passos anteriores terão que ser revisitados e possivelmente alterados
10/11/2014 Técnicas de Programação Avançada 47
Padrões de ProjetoDe Volta ao Exemplo Inicial
PopcornPopper
on()off()
pop()
TheaterLights
on()off()
dim()
Screen
up( )down()
CdPlayer
amplifier
on()off()eject()
pause()play()play()
stop()
Amplifier
turnerdvdPlayer
cdPlayer
on()
off()setCd()setDvd()
setStereoSound() setSurroundSoud()setTuner()
setVolume()
DvdPlayer
amplifier
on() off()eject()
pause()play() setSurroundAudio()
setTwoChannelAudio() stop()
Projector
dvdPlayer
on()off()tvMode()
wideScreenMode()
Turner
amplifier
on()off()setAm()
setFm()setFrequency()
HomeTheater
watchMovie()endMovie()listenToCd()
endCd()listenToRadio()endRadio()
10/11/2014 Técnicas de Programação Avançada 48
Padrões de Projeto
O Padrão Facade oferece uma interface única para um conjunto de interfaces de um subsistema e define uma interface de nível mais elevado que torna o subsistema mais fácil de usar.
O Padrão Facade
10/11/2014 Técnicas de Programação Avançada 49
Padrões de ProjetoSem o Padrão Facade
10/11/2014 Técnicas de Programação Avançada 50
Padrões de ProjetoCom o Padrão Facade
10/11/2014 Técnicas de Programação Avançada 51
Padrões de ProjetoUtilização do Padrão Adapter
O padrão Facade, portanto, introduz uma classe adicional quefunciona como uma fachada para o resto do sistema.
A interface disponibilizada por esta classe será a utilizada pelosclientes.
Esta interface, idealmente, deve ser simples e a própria classe facade deve se responsabilizar por traduzir os comandos simples nasinterações complexas com as demais classes do sistema.
10/11/2014 Técnicas de Programação Avançada 52
Padrões de ProjetoUtilização do Padrão Adapter
public class HomeTheaterFacade {
Amplifier amp; Tuner tuner; DvdPlayer dvd; CdPlayer cd;
Projector projector; TheaterLights lights; Screen screen; PopcornPopper popper;
public HomeTheaterFacade(Amplifier amp, Tuner tuner,
DvdPlayer dvd, CdPlayer cd, Projector projector, Screen screen,
TheaterLights lights, PopcornPopper popper) {
this.amp this.tuner = tuner;
this.dvd = dvd; this.cd = cd; this.projector = projector;
this.screen = screen; this.lights = lights; this.popper = popper;
// other methods here
}
}
10/11/2014 Técnicas de Programação Avançada 53
Padrões de ProjetoUtilização do Padrão Adapter
public void watchMovie(String movie) {
System.out.println(“Get ready to watch a movie...”);
popper.on(); popper.pop();
lights.dim(10); screen.down();
projector.on(); projector.wideScreenMode();
amp.on(); amp.setDvd(dvd); amp.setSurroundSound(); amp.setVolume(5);
dvd.on(); dvd.play(movie);
}
public void endMovie() {
System.out.println(“Shutting movie theater down...”);
popper.off(); lights.on(); screen.up();
projector.off(); amp.off(); dvd.stop(); dvd.eject(); dvd.off();
}
10/11/2014 Técnicas de Programação Avançada 54
Padrões de ProjetoUtilização do Padrão Adapter
Neste exemplo, a classe facade recebia em seu construtorreferências para as instâncias das classes internas do sistema.
Nada impede, no entanto, que a própria classe facade criasse estasinstâncias (por exemplo, em um construtor alternativo semargumentos).
Tendo uma classe facade, a interação do cliente com o resto do sistema é bastante simplificada.
10/11/2014 Técnicas de Programação Avançada 55
Padrões de ProjetoUtilização do Padrão Adapter
public class HomeTheaterTestDrive {
public static void main(String[] args) {
// instantiate components here
HomeTheaterFacade homeTheater =
new HomeTheaterFacade(amp, tuner, dvd, cd, projector, screen, lights, popper);
homeTheater.watchMovie(“Raiders of the Lost Ark”);
homeTheater.endMovie();
}
}
10/11/2014 Técnicas de Programação Avançada 56
Padrões de ProjetoO Padrão Facade - Participantes
Facade
Conhece quais classes do subsistema seriam responsáveis pelo atendimento de uma solicitação.
Delega solicitações de clientes a objetos apropriados do subsistemas.
Classes de subsistema
Implementam as funcionalidades do subsistema
Respondem a solicitações de serviços da Facade
Não têm conhecimento da Facade
10/11/2014 Técnicas de Programação Avançada 57
Padrões de ProjetoO Padrão Facade – Quando Usar
O padrão Facade é útil quando:
– Se deseja prover uma interface simples para um sistema complexo.
– Quando se deseja reduzir o acoplamento entre os clientes e as classes do sistema.
10/11/2014 Técnicas de Programação Avançada 58
Padrões de ProjetoO Padrão Facade – Análise
Note que o uso do padrão Facade não impede o uso das classes individuais do sistema por clientes “avançados”.
Note ainda que um mesmo sistema pode ter várias classes facade: cada uma provê uma API específica baseada nas mesmas classes internas.
10/11/2014 Técnicas de Programação Avançada 59
Padrões de ProjetoBibliografia
• Use a Cabeça ! Padrões de Projetos (design Patterns) - 2ª Ed. Elisabeth Freeman e Eric Freeman. Editora:Alta Books
• Padrões de Projeto – Soluçõesreutilizáveis de software orientado a objetos. Erich Gamma, Richard Helm, Ralph Johnson. Editora Bookman
• Bob Barr. The Adapter Pattern. http://userpages.umbc.edu/~tarr/dp/lectures/Adapter-2pp.pdf. Acessado em 02/03/2011 - 17:12 h