Le rôle de la numérisation des éléments dans l'ordre
package iterator;
public interface Iterator {
public abstract boolean hasNext();
public abstract Object next();
}
Le rôle d'implémentation de l'interface défini par le rôle d'itérateur
package iterator;
public class BookShelfIterator implements Iterator {
private BookShelf bookShelf;
private int index;
public BookShelfIterator(BookShelf bookShelf) {
this.bookShelf = bookShelf;
this.index = 0;
}
public boolean hasNext() {
return index < bookShelf.getLength();
}
public Object next() {
Book book = bookShelf.getBookAt(index);
index++;
return book;
}
}
Une interface qui crée le rôle d'itérateur.
package iterator;
public interface Aggregate {
public abstract Iterator iterator();
}
Un rôle qui implémente l'interface définie par le rôle Aggregate
package iterator;
import java.util.ArrayList;
import java.util.List;
public class BookShelf implements Aggregate {
private List<Book> books;
public BookShelf() {
this.books = new ArrayList<>();
}
public Book getBookAt(int index) {
return books.get(index);
}
public void appendBook(Book book) {
books.add(book);
}
public int getLength() {
return books.size();
}
public Iterator iterator() {
return new BookShelfIterator(this);
}
}
package iterator;
import java.util.ArrayList;
import java.util.List;
public class BookShelf implements Aggregate {
private List<Book> books;
public BookShelf() {
this.books = new ArrayList<>();
}
public Book getBookAt(int index) {
return books.get(index);
}
public void appendBook(Book book) {
books.add(book);
}
public int getLength() {
return books.size();
}
public Iterator iterator() {
return new BookShelfIterator(this);
}
}
package iterator;
public class Book {
private String name;
public Book(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
package iterator;
public class Main {
public static void main(String[] args) {
BookShelf bookShelf = new BookShelf();
bookShelf.appendBook(new Book("Effective Java"));
bookShelf.appendBook(new Book("CODE COMPLETE"));
bookShelf.appendBook(new Book("Code lisible"));
bookShelf.appendBook(new Book("Amélioration du code hérité"));
Iterator it = bookShelf.iterator();
while (it.hasNext()) {
Book book = (Book)it.next();
System.out.println(book.getName());
}
}
}
Pourquoi avons-nous besoin de créer un rôle Iterator en dehors de l'agrégat? La raison principale est qu'en utilisant Iterator, il est possible de compter séparément de l'implémentation.
while (it.hasNext()) {
Book book = (Book)it.next();
System.out.println(book.getName());
}
Seules les méthodes Iterator, hasNext et next, sont utilisées dans le code ci-dessus. Les méthodes utilisées dans l'implémentation BookShelf n'ont pas été appelées. Cette boucle ne dépend donc pas de l'implémentation de BookShelf.
Prenons le cas où BookShelf quitte la gestion des livres avec List et change pour utiliser des tableaux. Peu importe comment vous changez BookShelf, BookShelf a un itérateur Si vous retournez l'itérateur correct (s'il renvoie une instance de la classe dans laquelle les méthodes hasNext et next sont correctement implémentées), vous n'avez pas du tout besoin de modifier la boucle ci-dessus.
Les personnes qui ne sont pas familiarisées avec l'utilisation des classes abstraites et des interfaces ont tendance à programmer sur le rôle de Concrete Aggregate ou Concrete Iterator au lieu de l'interface Aggregate ou de l'interface Iterator (je le suis maintenant ...).
Si seules des classes spécifiques sont utilisées, les liens entre les classes seront solides et il sera difficile de les réutiliser en tant que parties.
Des classes abstraites et des interfaces sont introduites pour affaiblir la liaison et faciliter sa réutilisation en tant que composant de classe.
Recommended Posts