概念
与for循环类似,用于遍历容器元素,迭代器模式提供一种方式去访问一个容器元素中的各个对象,而又不暴露该对象的内部细节。
实现
案例:今天,我们学校组织春游,当我们乘上大巴准备出发的时候,老师让我点名答到,喊名字我也懒得喊了,等下喊破喉咙今天的快乐可都没了。那我就来写个程序吧,把名字打到公交车的显示屏上,用for循环太low了,今天我们得用个高级点的技术——迭代器模式
首先我们学生是主体,那肯定有学生类:
public class Student {
private String name;
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
接下来我们来定义一个迭代器:
public interface Iterator_ {
public abstract boolean hasNext();
public abstract Student next();
}
我们还需要一个容器的接口:
public interface Collection_ {
public abstract Iterator_ iterator();
public abstract void add(Student student);
}
现在我们需要定义容器的具体实现,我们现在在公交车上,就定义公交车吧:
public class Bus implements Collection_{
private List<Student> list;
public Bus() {
this.list = new ArrayList<>();
}
public Student getStudentAt(int index) {
return list.get(index);
}
@Override
public void add(Student student) {
list.add(student);
}
public int getLength() {
return list.size();
}
@Override
public Iterator_ iterator() {
return new BusIterator(this);
}
}
公交车好了,得知道在公交车上怎么数人啊,所以得在公交车上实现迭代的方式:
public class BusIterator implements Iterator_ {
//表示当前游标位置
private int current;
private Bus bus ;
public BusIterator(Bus bus) {
this.current = 0;
this.bus = bus;
}
@Override
public boolean hasNext() {
if(current >= bus.getLength()){
return false;
}
return true;
}
@Override
public Student next() {
Student student = bus.getStudentAt(current);
current++;
return student;
}
}
最后就是我们的测试类了:
public class Main {
public static void main(String[] args) {
Collection_ bus = new Bus();
bus.add(new Student("ctb"));
bus.add(new Student("xiaoming"));
bus.add(new Student("xiaohong"));
Iterator_ iterator_ = bus.iterator();
while (iterator_.hasNext()){
Student student = iterator_.next();
System.out.println(student.getName());
}
}
}
测试结果:
可能大家都察觉到了,这么简单的数数怎么不用个for循环呢,还要写这么多代码,多烧脑筋啊,所以说数组存储的数据不太需要使用迭代的方式进行遍历,如果是链表,hash表存储的数据,使用迭代的方式进行遍历,会变得简便很多:
下面给出使用链表存储的数据,通过迭代器模式进行遍历:
其中学生类,容器接口,迭代器接口同上
同样的,实现容器的具体类:
public class Bus implements Collection_ {
//容器中的元素个数
private int size = 0;
//头节点
public Node head = null;
//尾节点
public Node tail = null;
@Override
public void add(Student student){
Node node = new Node(student);
node.next = null;
//添加的元素为一个元素时
if(head == null){
head = node;
tail = node;
}
//将添加元素前的链表最后一个元素的尾节点设置为指向该元素
tail.next = node;
//将链表的最后一个元素设置为该元素
tail = node;
//长度加1
size++;
}
public int getSize(){
return size;
}
@Override
public Iterator_ iterator() {
return new BusIterator(this);
}
}
定义一个节点类:
public class Node {
private Student student;
public Node next;
public Node(Student student) {
this.student = student;
}
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
}
定义迭代器的具体实现类:
public class BusIterator implements Iterator_{
private Bus bus;
private Node node = null;
public BusIterator(Bus bus) {
this.bus = bus;
this.node = bus.head;
}
@Override
public boolean hasNext() {
if(node != null){
return true;
}else{
return false;
}
}
@Override
public Student next() {
Student student = node.getStudent();
node = node.next;
return student;
}
}
最后就是测试类:
public class Main {
public static void main(String[] args) {
Collection_ bus = new Bus();
bus.add(new Student("ctb"));
bus.add(new Student("xiaoming"));
bus.add(new Student("xiaohong"));
Iterator_ iterator_ = bus.iterator();
while (iterator_.hasNext()){
Student student = iterator_.next();
System.out.println(student.getName());
}
}
}
测试结果:
我们可以看到,测试类修改的地方不多,但是内部代码修改的量十分大,所以这种模式可以看出封装性良好。
优点:简化了遍历方式,封装性良好
缺点:对于像数组等简易容器,使用迭代器模式会变得相对繁琐
本文的代码:https://pan.baidu.com/s/1D57kMByPF2MtoVAEBxxdYw
提取码:goqk