• Nenhum resultado encontrado

Verificando-se sua defini¸c˜ao inicial observa-se que o padr˜ao Adapter tem por objetivo: “Converter a interface de uma classe em outra interface esperada pelos clientes. Adapter permite a comunica¸c˜ao entre classes que n˜ao poderiam trabalhar juntas devido `a incompa- tibilidade de suas interfaces” [Gamma et al., 1994]. Esta aplica¸c˜ao ´e geralmente utilizada em situa¸c˜oes onde um sistema ou parte dele ´e utilizado em outro sistema.

Observa-se, desta forma, que este padr˜ao de projetos pode ser bem aplicado quando seja necess´ario utilizar uma classe j´a existente, e a interface desenvolvida n˜ao ´e compat´ıvel com a referida classe. Outra forma de se aplicar este padr˜ao pode ser observada quando seja preciso criar uma classe reutiliz´avel, que se relaciona com classes distintas, sendo que estas classes n˜ao possuem necessariamente interfaces compat´ıveis, sendo necess´ario adaptar estas interfaces.

4.2.1

Exemplo utilizado para este padr˜ao

Para demonstrar a utiliza¸c˜ao deste padr˜ao, ´e utilizado um exemplo retirado de [Freeman et al., 2004], no qual s˜ao implementadas interfaces referentes a dois animais distintos: Patos (Duck) e Perus (Turkey). Estas interfaces possuem, cada uma, dois m´etodos. Para os patos,

os m´etodos s˜ao: quack() (referente ao som do pato) e fly() (vˆoo do pato). J´a no caso dos perus, temos os m´etodos gobble() (som do objeto peru) e fly() (semelhante ao m´etodo de vˆoo do objeto pato).

Percebe-se que as interfaces n˜ao s˜ao compat´ıveis. O objetivo aqui ´e fazer com que um objeto do tipo pato possa ser manipulado por meio de uma interface da classe peru, e vice-versa. Se formos simplesmente tentar utilizar uma interface de “pato” para um objeto “peru”, haver´a incompatibilidade de m´etodos, retornando erro na sa´ıda.

A solu¸c˜ao utilizada ´e a de criar duas classes do tipo “Adapter”. Uma das classes ser´a respons´avel por adaptar a interface da classe pato (Duck) com os objetos criados da classe peru (Turkey). Essa classe possui o nome TurkeyAdapter pois adapta o objeto da classe Turkey com a interface da classe Duck. Consequentemente, a classe que adapta os objetos da classe Duck com a interface da classe Turkey possui o nome DuckAdapter. A figura 4.1 mostra um diagrama de classes para melhor entendimento deste cen´ario.

Figura 4.1: Diagrama de classes do exemplo para o padr˜ao Adapter.

Al´em das interfaces Duck e Turkey, s˜ao definidas duas classes, uma relacionada com os patos, no caso MallardDuck, e outra relacionada com os perus, WildTurkey. As duas

Padrão Adapter 64

classes que funcionam como adaptadores, s˜ao DuckAdapter e TurkeyAdapter, conforme explicado anteriormente. Para complementar este exemplo, s˜ao criadas duas classes com o m´etodo principal (main()), sendo elas DuckTestDrive e TurkeyTestDrive. Ambas testam os adaptadores, verificando se obtiveram os resultados esperados.

4.2.2

Compara¸c˜ao das implementa¸c˜oes em Java e ooErlang

Em Java e ooErlang todas as classes e interfaces implementadas s˜ao similares. As interfaces Duck e Turkey s˜ao tamb´em similares, sendo que o diferencial entre elas ´e, princi- palmente, o m´etodo relacionado ao som do animal. Entretanto ambas possuem implemen- ta¸c˜oes semelhantes. Os c´odigos mostrados em 4.2.1 e 4.2.2 mostram as implementa¸c˜oes em Java e ooErlang, respectivamente, destas interfaces.

1 public interface Duck { 2 public void quack(); 3 public void fly(); 4 }

C´odigo 4.2.1: Interface Duck em Java

1 -interface(duck). 2 -export([quack/0, fly/0]). 3 4 methods. 5 6 quack(). 7 fly().

C´odigo 4.2.2: Interface Duck em ooErlang

A diferen¸ca entre a interface Duck e a interface Turkey ´e que, em Turkey, ao inv´es de existir o m´etodo quack(), existe o m´etodo gobble(). Esta ´e a incompatibilidade destas interfaces. A classe TurkeyAdapter implementa o adaptador que permite utilizar a interface Duck para uma instˆancia qualquer da classe WildTurkey, de acordo com o objetivo principal do padr˜ao Adapter. Os c´odigos mostrados em 4.2.3 e 4.2.4 mostram a implementa¸c˜ao do adaptador TurkeyAdapter em Java e ooErlang, nesta ordem.

1 public class TurkeyAdapter implements Duck { 2 Turkey turkey;

3

4 public TurkeyAdapter(Turkey turkey) { 5 this.turkey = turkey;

6 }

7

8 public void quack() { 9 turkey.gobble(); 10 }

11

12 public void fly() {

13 for(int i=0; i < 5; i++) { 14 turkey.fly();

15 }

16 } 17 }

C´odigo 4.2.3: Classe TurkeyAdapter em Java

1 -class(turkeyAdapter). 2 -implements(duck).

3 -export([new/1, quack/0, fly/0]). 4 -constructor([new/1]). 5 6 attributes. 7 8 Turkey. 9 10 methods. 11 12 new(Turkey) -> 13 self::Turkey = Turkey. 14 15 quack() -> 16 Temp = self::Turkey, 17 Temp::gobble(). 18 19 fly() -> 20 Temp = self::Turkey, 21 Temp::fly(), 22 Temp::fly(), 23 Temp::fly(), 24 Temp::fly(), 25 Temp::fly().

C´odigo 4.2.4: Classe TurkeyAdapter em ooErlang

Conforme pode ser observado, houveram adapta¸c˜oes para os dois m´etodos da classe WildTurkey, gobble() e fly(). Desta forma, o usu´ario ao fazer uso do adaptador TurkeyA- dapter, poder´a chamar os m´etodos da interface Duck para um objeto da classe WildTurkey,

Padrão Adapter 66

e observar que os resultados demonstram uma adapta¸c˜ao entre uma interface que inicial- mente era incompat´ıvel, mas que agora j´a pode ser utilizada para outro tipo de objeto, no caso, WildTurkey.

As classes DuckTestDrive e TurkeyTestDrive tem como objetivo verificar o funciona- mento dos adaptadores de interface para um objeto da classe WildTurkey utilizar a interface TurkeyAdapter e para um objeto da classe MallardDuck utilizar a interface DuckAdapter. Dessa forma, cada uma das classes acima citadas instancia um adaptador que deseja tes- tar para ser possivel verificar os resultados obtidos. Os c´odigos 4.2.5 e 4.2.6 mostram a implementa¸c˜ao da classe TurkeyTestDrive em Java e ooErlang respectivamente.

1 public class TurkeyTestDrive {

2 public static void main(String[] args) { 3 MallardDuck duck = new MallardDuck();

4 Turkey duckAdapter = new DuckAdapter(duck); 5

6 for(int i=0;i<10;i++) {

7 System.out.println("The DuckAdapter says..."); 8 duckAdapter.gobble();

9 duckAdapter.fly();

10 }

11 } 12 }

C´odigo 4.2.5: Classe principal TurkeyTestDrive em Java

1 -class(turkeyTestDrive). 2 -export([main/0]). 3 4 class_methods. 5 6 main() -> 7 Duck = mallardDuck::new_(), 8 DuckAdapter = duckAdapter::new(Duck), 9

10 io:format("The DuckAdapter says..."), 11 DuckAdapter::gobble(),

12 DuckAdapter::fly(),

13 io:format("The DuckAdapter says..."), 14 DuckAdapter::gobble(),

15 DuckAdapter::fly(),

16 io:format("The DuckAdapter says..."), 17 DuckAdapter::gobble(),

18 DuckAdapter::fly().

Desta forma, na implementa¸c˜ao mostrada, inicialmente ´e instanciado um objeto do tipo “pato”, pertencente `a classe MallardDuck. Em seguida este objeto ´e utilizado para que se possa instanciar uma classe que ir´a funcionar como adaptador, DuckAdapter, para verificar se o objeto originalmente do tipo “pato” pode ser utilizado com m´etodos da interface para o objeto “peru”. Dessa forma utilizam-se os dois m´etodos da interface Turkey, comprovando a compatibilidade gerada. As figuras 4.2 e 4.3 mostram o resultado da execu¸c˜ao deste exemplo em Java e ooErlang, respectivamente.

Figura 4.2: Execu¸c˜ao do exemplo para o padr˜ao Adapter em Java.

Este padr˜ao ´e comumente utilizado em muitos casos reais, devido `a facilidade e ne- cessidade de aplica¸c˜ao do mesmo em diferentes situa¸c˜oes. A implementa¸c˜ao em ooErlang mostrou-se semelhante `a utilizada em Java, e seus resultados demonstraram comporta- mento similar para ambas as linguagens de programa¸c˜ao. Este resultado demonstra a flexibilidade na programa¸c˜ao utilizando a extens˜ao ooErlang.

Padrão Bridge 68

Figura 4.3: Execu¸c˜ao do exemplo para o padr˜ao Adapter em ooErlang.

Algumas considera¸c˜oes devem ser feitas na utiliza¸c˜ao do padr˜ao de projetos Adapter. Por exemplo, o n´ıvel de adapta¸c˜ao que deve ser implementado, em rela¸c˜ao `a classe adaptada a sua relativa interface. Isto varia muito, havendo casos em que a adapta¸c˜ao deve ser total e, em outros casos, apenas parcial. Esta decis˜ao tem rela¸c˜ao estreita com o tipo de interface para a qual se ir´a implementar o adaptador. Caso esta interface n˜ao possua todos os m´etodos presentes na aplica¸c˜ao, ´e bem prov´avel que haja uma adapta¸c˜ao parcial na implementa¸c˜ao.