目录
迭代器模式(Iterator pattern)又叫游标(Cursor)模式,它的原始定义是:迭代器提供一种对容器对象中的各个元素进行访问的方法,而又不需要暴露该对象的内部细节。
迭代器模式是我们学习一个设计时很少用到的、但编码实现时却经常使用到的行为型设计模式。在绝大多数编程语言中,迭代器已经成为一个基础的类库,直接用来遍历集合对象。在平时开发中,我们更多的是直接使用它,很少会从零去实现一个迭代器。
在软件系统中,容器对象拥有两个职责:一是存储数据,而是遍历数据。从依赖性上看,前者是聚合对象的基本职责。而后者是可变化的,又是可分离的。因此可以将遍历数据的行为从容器中抽取出来,封装到迭代器对象中,由迭代器来提供遍历数据的行为,这将简化聚合对象的设计,更加符合单一职责原则。
迭代器模式主要包含以下角色:
package main.java.cn.test.iterator.V1;
/**
* @author ningzhaosheng
* @date 2024/1/15 15:23:06
* @description 迭代器接口
*/
public interface Iterator<E> {
//判断集合中是否有下一个元素
boolean hasNext();
//将游标后移一位元素
void next();
//返回当前游标指定的元素
E currentItem();
}
package main.java.cn.test.iterator.V1;
import java.util.ArrayList;
import java.util.NoSuchElementException;
/**
* @author ningzhaosheng
* @date 2024/1/15 15:23:43
* @description 具体迭代器
*/
public class ConcreteIterator<E> implements Iterator<E> {
//游标
private int cursor;
//容器
private ArrayList<E> arrayList;
public ConcreteIterator(ArrayList<E> arrayList) {
this.cursor = 0;
this.arrayList = arrayList;
}
@Override
public boolean hasNext() {
return cursor != arrayList.size();
}
@Override
public void next() {
cursor++;
}
@Override
public E currentItem() {
if (cursor >= arrayList.size()) {
throw new NoSuchElementException();
}
return arrayList.get(cursor);
}
}
package main.java.cn.test.iterator.V1;
import java.util.ArrayList;
/**
* @author ningzhaosheng
* @date 2024/1/15 15:25:35
* @description 测试类
*/
public class Test {
public static void main(String[] args) {
ArrayList<String> names = new ArrayList<>();
names.add("lisi");
names.add("zhangsan");
names.add("wangwu");
Iterator<String> iterator = new ConcreteIterator(names);
while (iterator.hasNext()) {
System.out.println(iterator.currentItem());
iterator.next();
}
/**
* 使用ArrayList集合中的iterator()方法获取迭代器
* 将创建迭代器的方法放入集合容器中,这样做的好处是对客户端封
装了迭代器的实现细节.
*/
java.util.Iterator<String> iterator1 = names.iterator();
while (iterator1.hasNext()) {
System.out.println(iterator1.next());
iterator.next();
}
}
}
为了帮助大家更好地理解迭代器模式,下面我还是通过一个简单的例子给大家演示一下
package main.java.cn.test.iterator.V2;
/**
* @author ningzhaosheng
* @date 2024/1/15 15:30:18
* @description 抽象迭代器 IteratorIterator
*/
public interface IteratorIterator<E> {
//重置为第一个元素
void reset();
//获取下一个元素
E next();
//检索当前元素
E currentItem();
//判断是否还有下一个元素存在
boolean hasNext();
}
package main.java.cn.test.iterator.V2;
/**
* @author ningzhaosheng
* @date 2024/1/15 15:31:11
* @description 抽象集合类
*/
public interface ListList<E> {
//获取迭代器对象的抽象方法(面向接口编程)
IteratorIterator<E> Iterator();
}
package main.java.cn.test.iterator.V2;
/**
* @author ningzhaosheng
* @date 2024/1/15 15:31:52
* @description 主题类
*/
public class Topic {
private String name;
public Topic(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package main.java.cn.test.iterator.V2;
/**
* @author ningzhaosheng
* @date 2024/1/15 15:32:22
* @description 具体迭代类
*/
public class TopicIterator implements IteratorIterator<Topic> {
//Topic数组
private Topic[] topics;
//记录存储位置
private int position;
public TopicIterator(Topic[] topics) {
this.topics = topics;
position = 0;
}
@Override
public void reset() {
position = 0;
}
@Override
public Topic next() {
return topics[position++];
}
@Override
public Topic currentItem() {
return topics[position];
}
@Override
public boolean hasNext() {
if (position >= topics.length) {
return false;
}
return true;
}
}
package main.java.cn.test.iterator.V2;
/**
* @author ningzhaosheng
* @date 2024/1/15 15:33:55
* @description 具体集合类
*/
public class TopicList implements ListList<Topic> {
private Topic[] topics;
public TopicList(Topic[] topics) {
this.topics = topics;
}
@Override
public IteratorIterator<Topic> Iterator() {
return new TopicIterator(topics);
}
}
package main.java.cn.test.iterator.V2;
/**
* @author ningzhaosheng
* @date 2024/1/15 15:35:00
* @description 测试类
*/
public class Test {
public static void main(String[] args) {
Topic[] topics = new Topic[4];
topics[0] = new Topic("topic1");
topics[1] = new Topic("topic2");
topics[2] = new Topic("topic3");
topics[3] = new Topic("topic4");
TopicList topicList = new TopicList(topics);
IteratorIterator<Topic> iterator = topicList.Iterator();
while (iterator.hasNext()) {
Topic t = iterator.next();
System.out.println(t.getName());
}
}
}
对于放入一个集合容器中的多个对象来说,访问必然涉及遍历算法。如果我们不将遍历算法封装到容器里(比如,List、Set、Map 等),那么就需要使用容器的人自行去实现遍历算法,这样容易造成很多重复的循环和条件判断语句出现,不利于代码的复用和扩展,同时还会暴露不同容器的内部结构。而使用迭代器模式是将遍历算法作为容器对象自身的一种“属性方法”来使用,能够有效地避免写很多重复的代码,同时又不会暴露内部结构。
迭代器模式把对不同集合类的访问逻辑抽象出来,这样在不用暴露集合内部结构的情况下,可以隐藏不同集合遍历需要使用的算法,同时还能够对外提供更为简便的访问算法接口。
好了,本次分享就到这里,欢迎大家继续阅读《设计模式》专栏其他设计模式内容,如果有帮助到大家,欢迎大家点赞+关注+收藏,有疑问也欢迎大家评论留言!