Sie sind auf Seite 1von 19

Padrão de Projeto Iterator

UNIVERSIDADE SÃO JUDAS TADEU


FACULDADE DE TECNOLOGIA E CIÊNCIAS EXATAS
CCP3AN-MCA

João Victor Rocha Ribeiro – R.A: 817126791


Leonardo Garcia de Souza - R.A: 81622108
Lucas Gustavo Barbosa - R.A: 81622845
Marcelo Palmito Moreno - R.A: 81620438
Victor Ricardo Hernandes -R.A: 817122837
Victoria Chelsea Lira Couto - R.A: 81716252

Professor Hamilton Machiti da Costa


SÃO PAULO
2019
Padrão de Projeto Iterator

● Classificado como comportamental – atuam na


comunicação entre os objetos e distribuição de
responsabilidades - Fornece uma maneira de
acessar sequencialmente os elementos de um
objeto agregado sem expor a sua representação.

● Oferece um objeto intermediário uniforme
(Iterator) que é utilizado entre o cliente e a coleção
de objetos. A ideia do iterador é de retirar da
coleção a responsabilidade de acessar e caminhar
na estrutura.

Participantes

● Iterator
● • Define um interface para o acesso e varredura;
● ConcreteIterator
● • Implementa a interface do Iterator;
● • Mantém referência (cursor) ao objeto que está sendo percorrido, podendo
calcular qual o elemento seguinte.

Aggregate
● • Define um interface para a criação do objeto Iterator;
● ConcreteAggregate
● • Implementa o método da interface que retorna uma instância do
ConcreteIterator (ArrayList, LinkedList, Vector).
● O método hasNext() verifica se existe um elemento
depois do atual. O método next() retorna esse
valor. É importante notar que o iterador que
cumpre esta interface não se posiciona em
nenhuma elemento quando é criado.
● O método hasNext() testa se o elemento seguinte
existe, no caso, ele verifica se o conjunto a iterar
não é vazio. O método next() é responsável por
prosseguir para o elemento seguinte e o retornar.
Problema

● Toda coleção possui uma representação interna


para o armazenamento e organização de seus
elementos, assim como mecanismos que permitam
o acesso aos mesmos. Os tipos mais utilizados no
ambiente Java:
● A interface de acesso aos elementos de uma coleção varia
causando problemas como o descrito abaixo: Uma empresa
de Tv a cabo gostaria de disponibilizar uma lista geral de
canais para todos seus assinantes. Durante a construção da
funcionalidade detectaram que o catálogo de canais, criado
anteriormente, foi implementado por duas equipes de
desenvolvedores distintas. Uma equipe ficou responsável
pelos canais nacionais e a outra por canais europeus.
● A equipe responsável pelos canais nacionais implementou o
catálogo de canais através de uma Matriz, enquanto a
equipe de canais europeus implementou utilizando um
ArrayList.
● Uma possível implementação da lista geral de canais seria:
ArrayList<Canal> arrayListDeCanaisEuropeus = new ArrayList<Canal>();
Canal[] matrizDeCanaisNacionais = new Canal[5];
System.out.println(“ -- Lista Geral de Canais -- ”);
for (Canal canal : arrayListDeCanaisEuropeus) {

System.out.println(canal.nome);
}
for (int i = 0; i < matrizDeCanaisNacionais.length; i++) {

System.out.println(matrizDeCanaisNacionais[i].nome);
}
● A implementação é funcional, mas observe os seguintes cenários:
• Uma das equipes decidiu alterar a implementação;
• Uma nova equipe é responsável por canais asiáticos, onde decidiram implementar através de
LinkedList. Teríamos que realizar a adequação do código em várias partes da aplicação, uma vez a
iteração sobre os diferentes tipos de implementação é distinto.
Solução

● A utilização de interfaces tornará a iteração sobre uma coleção uniforme


e independente da implementação concreta.
● Definiremos uma interface comum à todos os objetos agregados, ou seja
uma lista genérica:

public interface AgregadoDeCanais {

IteradorInterface criarIterator();
● }

A interface não possui nenhum detalhe da implementação da lista,
apenas define a implementação do método criarIterator nas classes
agregadoras.

Na classe concreta, utilizaremos a lista já implementada e realizaremos a
implementação do método criarIterator da interface AgregadoDeCanais.
public class CanaisEsportes implements AgregadoDeCanais {
protected ArrayList<Canal> canais;
public CanaisNacionais() {
canais = new ArrayList<Canal>();
canais.add(new Canal("Tv Cultura"));
canais.add(new Canal("Band"));
canais.add(new Canal("Rede Tv"));
}
@Override
public IteradorInterface criarIterator() {
return new IteradorListaDeCanais(canais);
}
}
● O método criarIterator retorna um iterador de lista, que possui como conjunto de dados a lista
implementada. Na classe que utiliza uma matriz, o método de criarIterator retorna um iterador de Matriz.
@Override
public IteradorInterface criarIterator() {
return new IteradorMatrizDeCanais(canais);
}
● Todas as diferentes implementações de coleção estão encapsuladas e possuem uma interface comum.
● Da mesma maneira que criamos uma interface comum aos agregados vamos criar uma interface comum aos
iteradores, assim podemos garantir que todo iterador tenha operações necessárias para percorrer o
conjunto de dados.
public interface IteradorInterface {
void first();
void next();
boolean isDone();
Canal currentItem();
}
● Esta interface segue a recomendação do GoF [1].
Ou seja todo iterador possui um método que inicia
o iterador (first), avança o iterador (next), verifica
se já encerrou o percurso (isDone) e o que retorna
o objeto atual (currentItem).
● A implementação desses métodos será feita no
iterador concreto, levando em consideração o tipo
do conjunto de dados.
public class IteradorListaDeCanais implements IteradorInterface {

protected ArrayList<Canal> lista;


protected int contador;

protected IteradorListaDeCanais(ArrayList<Canal> lista) {


this.lista = lista;
contador = 0;
}
public void first() {
contador = 0;
}
public void next() {
contador++;
}
public boolean isDone() {
return contador == lista.size();
}
public Canal currentItem() {
if (isDone()) {
contador = lista.size() - 1;
} else if (contador < 0) {
contador = 0;
}
return lista.get(contador);
}
}
● Os métodos alteram o contador do iterador, que marca qual o
elemento está sendo visitado e, no método que retorna o objeto
nós verificamos se o contador está dentro dos limites válidos e
retornamos o objeto corrente.
public class IteradorMatrizDeCanais implements
IteradorInterface {
protected Canal[] lista;
protected int contador;
public IteradorMatrizDeCanais(Canal[] lista) {
this.lista = lista;
}
@Override
public void first() {
contador = 0;
}
@Override
public void next() {
contador++;
}
@Override
public boolean isDone() {
return contador == lista.length;
}
@Override
public Canal currentItem() {
if (isDone()) {
contador = lista.length - 1;
} else if (contador < 0) {
contador = 0;
}
return lista[contador];
}
}

A maneira de percorrer a lista de dados está encapsulada. O código para consumir a lista geral de
canais ficaria:
public static void main(String[] args) {
AgregadoDeCanais canaisNacionais = new CanaisNacionais();
System.out.println("Canais Nacionais:");
for (IteradorInterface it = canaisNacionais.criarIterator(); !it
.isDone(); it.next()) {
System.out.println(it.currentItem().nome);
}
AgregadoDeCanais canaisEuropeus = new CanaisEuropeus();
System.out.println("\nCanais Europeus:");
for (IteradorInterface it = canaisEuropeus.criarIterator(); !it
.isDone(); it.next()) {
System.out.println(it.currentItem().nome);
}
}
Bibliografia

● Eric Freeman, Elisabeth Robson, Bert Bates, Kathy


Sierra. Head First Design Patterns. O'Reilly Media,
2004.
● Gamma, E., Helm, R., Johnson, R., Vlissides, J.
Design Patterns: Elements of Reusable Object-
Oriented Software. Addison Wesley, 2010.

Das könnte Ihnen auch gefallen