迭代器模式,存储数据与遍历数据的分离
2022-05-05 本文已影响0人
程就人生
你是否每次要遍历一个集合时,总是若有所思?
集合的遍历,是怎么迭代的来?有没有通用法则?
你有没有想过,自己来实现一个迭代器?
迭代器模式(Iterator Pattern),是一种顺序访问聚合对象的行为型模式,它把存储数据和遍历数据进行了解耦。使用户不必关心集合对象的底层表示,即可顺序地访问集合中的对象。
业务场景:需要把存储数据和遍历数据分开处理的场合。
关键代码:hasNext和next;hasNext表示还有没有下一个对象;next则表示访问下一个对象。
下面看UML类图:
UML类图说明:IIterator负责数据遍历,IContainer负责数据存储,NameRepository又聚合了NameIterator,关系非常简单。
代码实现步骤:
- 迭代器接口;
/**
* 1.遍历接口
* @author 程就人生
* @Date
*/
public interface IIterator<T> {
// 还有没有下一个元素
public boolean hasNext();
// 读取下一个元素
public T next();
}
2.容器接口;
/**
* 2.容器接口
* @author 程就人生
* @Date
*/
public interface IContainer<T> {
// 迭代集合中所有的元素
public IIterator<T> getIterator();
}
3.容器实现类;
import java.util.ArrayList;
import java.util.List;
/**
* 3.容器实现类
* @author 程就人生
* @Date
*/
public class NameRepository implements IContainer<String>{
private List<String> nameList;
public NameRepository(){
nameList = new ArrayList<String>();
}
public void add(String name){
nameList.add(name);
}
@Override
public IIterator<String> getIterator() {
return new NameIterator(nameList);
}
}
4.迭代器实现类;
import java.util.List;
/**
* 4. 遍历数据的具体实现
* @author 程就人生
* @Date
*/
public class NameIterator implements IIterator<String>{
private int index;
private List<String> nameList;
public NameIterator(List<String> nameList){
this.nameList =nameList;
}
@Override
public boolean hasNext() {
// 有则返回true,否则返回false
if(nameList != null && index < nameList.size()){
return true;
}
return false;
}
@Override
public String next() {
if(this.hasNext()){
return nameList.get(index++);
}
return null;
}
}
也可以把迭代器作为容器实现类的内部类来实现;
import java.util.ArrayList;
import java.util.List;
/**
* 3.NameRepository实现了容器接口
* @author 程就人生
* @Date
*/
public class NameRepository implements IContainer<String>{
private static List<String> nameList;
public NameRepository(){
nameList = new ArrayList<String>();
}
public void add(String name){
nameList.add(name);
}
@Override
public IIterator<String> getIterator() {
return new NameIterator();
}
/**
* 3.1 内部类实现了遍历接口,遍历数据的具体实现
* @author 程就人生
* @Date
*/
private class NameIterator implements IIterator<String>{
private int index;
@Override
public boolean hasNext() {
if(nameList != null && index < nameList.size()){
return true;
}
return false;
}
@Override
public String next() {
if(this.hasNext()){
return nameList.get(index++);
}
return null;
}
}
}
5.测试代码;
public static void main(String[] argo){
NameRepository nameRepository = new NameRepository();
// 数据存储
nameRepository.add("张三");
nameRepository.add("王五");
nameRepository.add("李四");
// 数据遍历,存在下一个时,则打印下一个对象
for(IIterator<String> iterator = nameRepository.getIterator(); iterator.hasNext();){
System.out.println(iterator.next());
}
}
}
测试结果:
张三
王五
李四
这段代码的意思是:创建一个动态存储名称的容器NameRepository,其中NameIterator类通过hasNext判断是否还有下一个元素,通过Next获取下一个元素,如此循环,直至把聚合对象中的元素全部遍历完毕。
NameIterator即可作为一个单独的类处理,又可聚合到NameRepository对象里面,作为该对象的内部类使用。至此,一个简单的迭代器模式编码完成。
最后总结
迭代器模式,主要负责存储数据和遍历数据的分离。它是一种很好理解,又经常使用的行为型模式。
思考题:列举一下在项目中,各种集合的遍历是如何实现的吧!