Difference between revisions of "Visitor (padrão de desenho)"

From Wiki**3

Line 1: Line 1:
Material correspondente à aula 29.
+
{{TOCright}}
 
 
 
O padrão ''visitor'' permite separar uma estrutura de objectos de algoritmos que a ela possam ser associados em tempo de execução. A adição do comportamento processa-se sem alteração objecto "visitado".
 
O padrão ''visitor'' permite separar uma estrutura de objectos de algoritmos que a ela possam ser associados em tempo de execução. A adição do comportamento processa-se sem alteração objecto "visitado".
  
Line 11: Line 10:
 
[[Image:visitor-dpcd.png|600px]]
 
[[Image:visitor-dpcd.png|600px]]
  
===Diagrama de sequência===
+
===Diagrama de sequência===
  
As colaborações entre os intervenientes são as que figuram no seguinte diagrama de sequência:
+
As colaborações entre os intervenientes são as que figuram no seguinte diagrama de sequência:
  
 
[[Image:visitor-dpsd.png|600px]]
 
[[Image:visitor-dpsd.png|600px]]
Line 23: Line 22:
 
Os visitantes implementam a interface <code>Visitante</code>:
 
Os visitantes implementam a interface <code>Visitante</code>:
  
  <FONT COLOR="#0000ff">interface</FONT> Visitante {
+
<java5>
     <FONT COLOR="#0000ff">void</FONT> visita(Alface g);
+
  interface Visitante {
     <FONT COLOR="#0000ff">void</FONT> visita(Batata r);
+
     void visita(Alface g);
     <FONT COLOR="#0000ff">void</FONT> visita(Cebola c);
+
     void visita(Batata r);
 +
     void visita(Cebola c);
 
   }
 
   }
 +
</java5>
  
Note-se que esta interface prevê que os métodos sejam seleccionados por um mecanismo da linguagem (''overloading'') em lugar de se definir um conjunto de métodos com nomes explicitamente distintos.
+
Note-se que esta interface prevê que os métodos sejam seleccionados por um mecanismo da linguagem (''overloading'') em lugar de se definir um conjunto de métodos com nomes explicitamente distintos.
  
 
A primeira implementação adiciona a capacidade de descrição a cada produto hortícola.
 
A primeira implementação adiciona a capacidade de descrição a cada produto hortícola.
  
  <FONT COLOR="#0000ff">class</FONT> Descri&ccedil;&atilde;o <FONT COLOR="#0000ff">implements</FONT> Visitante {
+
<java5>
     String s;   
+
  class Descrição implements Visitante {
     <FONT COLOR="#0000ff">public</FONT> String toString() { <FONT COLOR="#0000ff">return</FONT> s; }
+
     private String s;   
     <FONT COLOR="#0000ff">public</FONT> <FONT COLOR="#0000ff">void</FONT> visita(Alface a) { s = <FONT COLOR="#004488">&quot;Alface&quot;</FONT>; }
+
     public String toString()     { return s; }
     <FONT COLOR="#0000ff">public</FONT> <FONT COLOR="#0000ff">void</FONT> visita(Batata b) { s = <FONT COLOR="#004488">&quot;Batata&quot;</FONT>; }
+
     public void visita(Alface a) { s = "Alface"; }
     <FONT COLOR="#0000ff">public</FONT> <FONT COLOR="#0000ff">void</FONT> visita(Cebola c) { s = <FONT COLOR="#004488">&quot;Cebola&quot;</FONT>; }
+
     public void visita(Batata b) { s = "Batata"; }
 +
     public void visita(Cebola c) { s = "Cebola"; }
 
   }
 
   }
 +
</java5>
  
A primeira implementação simula a capacidade de interacção entre um animal (visitante) e um produto hortícola.
+
A primeira implementação simula a capacidade de interacção entre um animal (visitante) e um produto hortícola.
  
  <FONT COLOR="#0000ff">class</FONT> Animal <FONT COLOR="#0000ff">implements</FONT> Visitante {   
+
<java5>
     <FONT COLOR="#0000ff">public</FONT> <FONT COLOR="#0000ff">void</FONT> visita(Alface a) { System.out.println(<FONT COLOR="#004488">&quot;Animal &amp; Alface&quot;</FONT>); }
+
  class Animal implements Visitante {   
     <FONT COLOR="#0000ff">public</FONT> <FONT COLOR="#0000ff">void</FONT> visita(Batata b) { System.out.println(<FONT COLOR="#004488">&quot;Animal &amp; Batata&quot;</FONT>); }
+
     public void visita(Alface a) { System.out.println("Animal & Alface"); }
     <FONT COLOR="#0000ff">public</FONT> <FONT COLOR="#0000ff">void</FONT> visita(Cebola c) { System.out.println(<FONT COLOR="#004488">&quot;Animal &amp; Cebola&quot;</FONT>); }
+
     public void visita(Batata b) { System.out.println("Animal & Batata"); }
 +
     public void visita(Cebola c) { System.out.println("Animal & Cebola"); }
 
   }
 
   }
 +
</java5>
  
 
=== Produtos ===
 
=== Produtos ===
  
A hierarquia de produtos hortícolas implementa uma interface comum que impõe a aceitação de visitantes.
+
A hierarquia de produtos hortícolas implementa uma interface comum que impõe a aceitação de visitantes.
  
  <FONT COLOR="#0000ff">interface</FONT> Hort&iacute;cola {
+
<java5>
     <FONT COLOR="#0000ff">void</FONT> aceita(Visitante v);
+
  interface Hortícola {
 +
     void aceita(Visitante v);
 
   }
 
   }
 +
</java5>
  
 
Note-se que as várias implementações são meras esquematizações: a semelhança entre as implmentações do método <code>aceita</code> resulta da simplicidade do exemplo (o método pode ser, como seria de esperar, arbitrariamente complexo).
 
Note-se que as várias implementações são meras esquematizações: a semelhança entre as implmentações do método <code>aceita</code> resulta da simplicidade do exemplo (o método pode ser, como seria de esperar, arbitrariamente complexo).

Revision as of 01:28, 14 November 2008

O padrão visitor permite separar uma estrutura de objectos de algoritmos que a ela possam ser associados em tempo de execução. A adição do comportamento processa-se sem alteração objecto "visitado".

Estrutura

Diagrama de classes

O padrão visitor tem a seguinte estrutura de classes:

Visitor-dpcd.png

Diagrama de sequência

As colaborações entre os intervenientes são as que figuram no seguinte diagrama de sequência:

Visitor-dpsd.png

Exemplo

Visitantes

Os visitantes implementam a interface Visitante:

<java5>

 interface Visitante {
   void visita(Alface g);
   void visita(Batata r);
   void visita(Cebola c);
 }

</java5>

Note-se que esta interface prevê que os métodos sejam seleccionados por um mecanismo da linguagem (overloading) em lugar de se definir um conjunto de métodos com nomes explicitamente distintos.

A primeira implementação adiciona a capacidade de descrição a cada produto hortícola.

<java5>

 class Descrição implements Visitante {
   private String s;  
   public String toString()     { return s; }
   public void visita(Alface a) { s = "Alface"; }
   public void visita(Batata b) { s = "Batata"; }
   public void visita(Cebola c) { s = "Cebola"; }
 }

</java5>

A primeira implementação simula a capacidade de interacção entre um animal (visitante) e um produto hortícola.

<java5>

 class Animal implements Visitante {  
   public void visita(Alface a) { System.out.println("Animal & Alface"); }
   public void visita(Batata b) { System.out.println("Animal & Batata"); }
   public void visita(Cebola c) { System.out.println("Animal & Cebola"); }
 }

</java5>

Produtos

A hierarquia de produtos hortícolas implementa uma interface comum que impõe a aceitação de visitantes.

<java5>

 interface Hortícola {
   void aceita(Visitante v);
 }

</java5>

Note-se que as várias implementações são meras esquematizações: a semelhança entre as implmentações do método aceita resulta da simplicidade do exemplo (o método pode ser, como seria de esperar, arbitrariamente complexo).

 class Alface implements Hortícola {  
   public void aceita(Visitante v) { v.visita(this); }
 }
 class Batata implements Hortícola {  
   public void aceita(Visitante v) { v.visita(this); }
 }
 class Cebola implements Hortícola {  
   public void aceita(Visitante v) { v.visita(this); }
 }

Teste

O teste utiliza uma factory simples para gerar produtos hortícolas aleatórios.

 class Horta {
   public static Hortícola produto() {
     switch((int)(Math.random() * 3)) {
       default:
       case 0: return new Alface();
       case 1: return new Batata();
       case 2: return new Cebola();
     }
   }
 }

Note-se a acção dos visitantes no seguinte teste.

 public class Teste extends TestCase {
   List<Hortícola> _produtos = new ArrayList<Hortícola>();

   public Teste() {
     for(int i = 0; i < 10; i++)
       _produtos.add(Horta.produto());
   }

   public void test() {
     // Apresenta as descrições de cada produto
     Descrição dsc = new Descrição();
     for (Hortícola h : _produtos) {
       h.aceita(dsc);
       System.out.println(dsc);
     }

     // Animal visita horta
     Animal a = new Animal();
     for (Hortícola h : _produtos)
       h.aceita(a);
   }

   public static void main(String args[]) {
     new Teste().test();
   }
 }