Iterator模式——–一个一个遍历
大家可以先跟着以下的步骤,具体实现一遍,体会一下代码具体的含义,最后如有疑惑,可以看文后的总结,这也是当时我看这个设计模式心中的疑惑。
目录:
public interface Aggregate {
public Iterator iterator();
}
该接口中只声明了一个方法–iterator。目的是在后续的Zoo类中实现该接口,调用iterator方法实现Iterator接口的类的实例。
Iterator接口
public interface Iterator {
//判断集合中下个元素是否为空
public boolean hasNext();
//输出集合中的当前对象,并指向集合中的下一个元素
public Object next();
}
该接口声明了两个方法,其中hasNext方法判断集合中下一个元素是否为空,若不为空返回true,否则返回false。
而next方法则是返回集合中的当前元素,并指向集合中的下一个元素,具体算法会在ZooIterator类中实现。.
动物实体类
public class Animal {
private String animalName;
public String getAnimalName() {
return animalName;
}
public Animal(String animalName) {
this.animalName = animalName;
}
}
动物园
//实现Aggregate接口
public class Zoo implements Aggregate {
//定义泛型为Animal的ArrayList,此处设置private,是为了防止外部不小心修改该字段的值
private List<Animal> animalsList = new ArrayList<>();
//根据索引返回List中指定下标的Animal对象
public Animal getAnimalByIndex(int index){
return animalsList.get(index);
};
//向动物园中添加小动物
public void addAnimal(Animal animal){
animalsList.add(animal);
}
//获取Zoo的大小----动物园里面有多少小动物
public int getLength(){
return animalsList.size();
}
//实现Aggregate接口中的iterator方法,并在方法中返回ZooIterator的实例,其中参数this指的是当前类Zoo----动物园
public Iterator iterator(){
return new ZooIterator(this);
}
}
Zoo类是代表着动物的集合的类,所以它实现了Aggregate 接口,并实现了Aggregate 接口中的iterator方法。
同时,在iterator方法中生成ZooIterator的实例,并在ZooIterator的实例中返回Zoo对应的Iterator—-基于当前Zoo返回的hasNext和next
遍历动物园
public class ZooIterator implements Iterator{
private Zoo zoo;
private int index;
//将接收到的参数赋值
public ZooIterator(Zoo zoo){
this.zoo = zoo;
this.index = 0;
}
//hasNext的具体实现
@Override
public boolean hasNext() {
//当前下标未超过zoo的总大小时,返回true否则返回false
if( index < zoo.getLength()){
return true;
//也可看做当前指的第几个小动物,是否超过了动物园的总动物数量,
//若是超出自然不会有对应的小动物,自然返回false
}
return false;
}
//next的具体实现
@Override
public Object next() {
//根据当前下标,返回当前的animal对象
Animal animal = zoo.getAnimalByIndex(index);
//下标加一,意味着指向下一个对象
index++;
return animal;
//此处也可看做,点到小动物对应的编号,小动物出列,同时报出下一个小动物的编号,
//若是还有对应的小动物,则继续出列,以此类推...
}
}
该类实现了Iterator接口,将hasNext方法和next方法具体实现.
测试
public class Main {
public static void main(String[] args) {
Zoo zoo = new Zoo();
zoo.addAnimal(new Animal("dog"));
zoo.addAnimal(new Animal("cat"));
zoo.addAnimal(new Animal("tiger"));
zoo.addAnimal(new Animal("horse"));
Iterator iterator = zoo.iterator();
while (iterator.hasNext()){
Animal animal = (Animal) iterator.next();
System.out.println(animal.getAnimalName());
}
}
}
向zoo中添加多个Animal对象.
结果
总结
相信很多人在操作完后都会有个巨大的疑惑,明摆着一个foreach就能解决的问题,为什么要用这么麻烦的方式?
实际上,该设计模式给我们带来的是一个”可复用“的组件—– Zoo :
public class Zoo implements Aggregate{
private List<Animal> animalsList = new ArrayList<>();
// 此处用数组管理小动物
// private Animal[] animals;
// private int last = 0;
// 实例化时,指定数组大小
// public Zoo(int maxsize){
// this.animals = new Animal[maxsize];
// }
public Animal getAnimalByIndex(int index){
return animalsList.get(index);
};
public void addAnimal(Animal animal){
animalsList.add(animal);
}
// 数组的方式添加小动物
// public void addAnimal(Animal animal){
// this.animals[last] = animal;
// last++;
// }
public int getLength(){
return animalsList.size();
}
public Iterator iterator(){
return new ZooIterator(this);
}
}
上面的注释处的改动,便是能够将以ArrayList管理小动物转换成用数组来管理小动物,而其余的代码基本保持不动,因为只要Zoo 类中iterator方法能正确的返回Iterator的实例,hasNext方法和next方法便可以正常使用.
由此,我们可以想象一下,若是Zoo 被别的方法调用了无数次之后,突然动物园园长不想要用ArrayList 来管理了,想要用数组的形式来管理,该怎么办?
若是我们当时用的是foreach 的形式来遍历的话,恐怕需要修改个无数遍,这就非常麻烦了,这时,Iterator设计模式的应用,就能给我们带来很多便利,因为他只要像如上所示来修改Zoo类,那么这一切问题都会迎刃而解!