迭代器模式(Iterator Pattern)是一种行为型设计模式,它允许客户端逐步访问聚合对象的元素,而不暴露其底层表现形式。本文将从定义、结构和实现等多个角度介绍迭代器模式,并提供一个实例来说明它的用法。
定义
迭代器模式定义了一种方法,通过它可以顺序地访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部结构。它通过提供一个迭代器来实现该功能,该迭代器可以按需生成聚合对象的下一个元素。在软件开发中,在一个聚合对象有不同表现形式的情况下,可以使用迭代器模式抽象出它们的共性,并分离它们的变化和不变化的部分。
结构
迭代器模式的核心是迭代器(Iterator),它抽象出所有迭代器的共性操作:
```
abstract class Iterator {
abstract boolean hasNext();
abstract Object Next();
}
```
聚合对象(Aggregate)定义了创建迭代器的接口:
```
interface Aggregate {
Iterator createIterator();
}
```
具体聚合对象(Concrete Aggregate)实现了创建迭代器的接口,并存储其元素以供迭代器访问:
```
class ConcreteAggregate implements Aggregate {
private Object[] elements;
ConcreteAggregate(Object[] elements) {
this.elements = elements;
}
@Override
public Iterator createIterator() {
return new ConcreteIterator(this);
}
Object getElement(int index) {
return elements[index];
}
int size() {
return elements.length;
}
}
```
具体迭代器(Concrete Iterator)实现了迭代器接口,并持有对聚合对象的引用:
```
class ConcreteIterator extends Iterator {
private ConcreteAggregate aggregate;
private int index;
ConcreteIterator(ConcreteAggregate aggregate) {
this.aggregate = aggregate;
this.index = 0;
}
@Override
boolean hasNext() {
return index < aggregate.size();
}
@Override
Object Next() {
if (hasNext()) {
return aggregate.getElement(index++);
}
return null;
}
}
```
实现
现在,我们假设要实现一个文件浏览器,可以遍历一个文件夹中的所有文件。我们可以借助迭代器模式来实现该功能。首先,我们需要定义一个聚合对象抽象类,它可以是文件或文件夹:
```
abstract class FileSystemItem {
protected String name;
FileSystemItem(String name) {
this.name = name;
}
abstract void add(FileSystemItem item);
abstract void remove(FileSystemItem item);
abstract Iterator createIterator();
}
```
对于文件夹,它可以包含多个文件或文件夹:
```
class Folder extends FileSystemItem {
private List
Folder(String name) {
super(name);
items = new ArrayList<>();
}
@Override
void add(FileSystemItem item) {
items.add(item);
}
@Override
void remove(FileSystemItem item) {
items.remove(item);
}
@Override
Iterator createIterator() {
return new FolderIterator(this);
}
// ...
}
```
对于文件,它可以直接遍历:
```
class File extends FileSystemItem {
File(String name) {
super(name);
}
@Override
void add(FileSystemItem item) {
// do nothing
}
@Override
void remove(FileSystemItem item) {
// do nothing
}
@Override
Iterator createIterator() {
return new NullIterator();
}
// ...
}
```
接下来,我们实现一个具体迭代器来遍历文件夹:
```
class FolderIterator extends Iterator {
private Folder folder;
private int index;
private Iterator subIterator;
FolderIterator(Folder folder) {
this.folder = folder;
index = 0;
subIterator = null;
}
@Override
boolean hasNext() {
if (subIterator != null && subIterator.hasNext()) {
return true;
}
if (index < folder.getItems().size()) {
FileSystemItem item = folder.getItems().get(index);
if (item instanceof Folder) {
subIterator = ((Folder) item).createIterator();
return hasNext();
} else {
index++;
return true;
}
}
return false;
}
@Override
Object Next() {
if (hasNext()) {
if (subIterator != null && subIterator.hasNext()) {
return subIterator.Next();
} else {
FileSystemItem item = folder.getItems().get(index);
index++;
return item;
}
}
return null;
}
}
```
如果文件夹中包含了另一个文件夹,遍历器就会递归地访问其中的文件和文件夹。如果只有文件,迭代器只需要返回它本身即可。此外,我们还需要实现一个空迭代器,用于遍历文件:
```
class NullIterator extends Iterator {
@Override
boolean hasNext() {
return false;
}
@Override
Object Next() {
return null;
}
}
```
通过这些类的组合和迭代器的遍历,我们可以实现文件浏览器的遍历功能。
扫码咨询 领取资料