目录
一、迭代器模式介绍
1.1 迭代器模式定义
1.2 迭代器模式原理
1.2.1 迭代器模式类图
1.2.2 模式角色说明
1.2.3 示例代码
二、迭代模式的应用
2.1 需求说明
2.2 需求实现
2.2.1 抽象迭代类
2.2.2 抽象集合类
2.2.3 主题类
2.2.4 具体迭代类
2.2.5 具体集合类
2.2.6 测试类
三、迭代器模式总结
3.1 迭代器模式的优点
3.2 迭代器模式的缺点
3.3 迭代器模式的使用场景
迭代器模式(Iterator pattern)又叫游标(Cursor)模式,它的原始定义是:迭代器提供一种对容器对象中的各个元素进行访问的方法,而又不需要暴露该对象的内部细节。
迭代器模式是我们学习一个设计时很少用到的、但编码实现时却经常使用到的行为型设计模式。在绝大多数编程语言中,迭代器已经成为一个基础的类库,直接用来遍历集合对象。在平时开发中,我们更多的是直接使用它,很少会从零去实现一个迭代器。
在软件系统中,容器对象拥有两个职责:一是存储数据,而是遍历数据。从依赖性上看,前者是聚合对象的基本职责。而后者是可变化的,又是可分离的。因此可以将遍历数据的行为从容器中抽取出来,封装到迭代器对象中,由迭代器来提供遍历数据的行为,这将简化聚合对象的设计,更加符合单一职责原则。
迭代器模式主要包含以下角色:
package main.java.cn.test.iterator.V1;
/**
* @author ningzhaosheng
* @date 2024/1/15 15:23:06
* @description 迭代器接口
*/
public interface Iterator {
//判断集合中是否有下一个元素
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 implements Iterator {
//游标
private int cursor;
//容器
private ArrayList arrayList;
public ConcreteIterator(ArrayList 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 names = new ArrayList<>();
names.add("lisi");
names.add("zhangsan");
names.add("wangwu");
Iterator iterator = new ConcreteIterator(names);
while (iterator.hasNext()) {
System.out.println(iterator.currentItem());
iterator.next();
}
/**
* 使用ArrayList集合中的iterator()方法获取迭代器
* 将创建迭代器的方法放入集合容器中,这样做的好处是对客户端封
装了迭代器的实现细节.
*/
java.util.Iterator 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 {
//重置为第一个元素
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 {
//获取迭代器对象的抽象方法(面向接口编程)
IteratorIterator 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数组
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 {
private Topic[] topics;
public TopicList(Topic[] topics) {
this.topics = topics;
}
@Override
public IteratorIterator 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 iterator = topicList.Iterator();
while (iterator.hasNext()) {
Topic t = iterator.next();
System.out.println(t.getName());
}
}
}
对于放入一个集合容器中的多个对象来说,访问必然涉及遍历算法。如果我们不将遍历算法封装到容器里(比如,List、Set、Map 等),那么就需要使用容器的人自行去实现遍历算法,这样容易造成很多重复的循环和条件判断语句出现,不利于代码的复用和扩展,同时还会暴露不同容器的内部结构。而使用迭代器模式是将遍历算法作为容器对象自身的一种“属性方法”来使用,能够有效地避免写很多重复的代码,同时又不会暴露内部结构。
迭代器模式把对不同集合类的访问逻辑抽象出来,这样在不用暴露集合内部结构的情况下,可以隐藏不同集合遍历需要使用的算法,同时还能够对外提供更为简便的访问算法接口。
好了,本次分享就到这里,欢迎大家继续阅读《设计模式》专栏其他设计模式内容,如果有帮助到大家,欢迎大家点赞+关注+收藏,有疑问也欢迎大家评论留言!