迭代器模式
说起迭代器,我们会比较熟悉,Iterator,出现在聚合里,提供了访问聚合中包含的对象的功能,迭代器提供了一系列相同的方法,比如hasnext()、next()等等,我们利用迭代器对聚合进行访问时,不需要知道聚合中如何存储存储一系列对象,我们只需要操作迭代器来进行访问。
迭代器模式把访问聚合对象的功能抽取出来,如何访问对象由迭代器自己实现,使聚合对其包含对象的访问中解耦出来。
下面是结构图,十分简单:
迭代器只需要实现Iterator结构,自己实现里面的方法,我这里只实现了hasNext跟next方法,下面我把它应用到上一次讲的组合模式中,让组合模式中的文件夹不需要编写对其所包含的文件的访问,访问功能有迭代器提供。
FileCompoment改造:
public interface FileCompoment {
Iterator iterator(); //增加了一个接口,用来获取迭代器
}
public class FileBase implements FileCompoment{
@Override
public Iterator iterator() {
return new NullIterator(); //返回一个空迭代器,hasNext()方法一定是false
}
}
public class FolderBase implements FileCompoment {
@Override
public void print() {
// 注释掉原本的对包含的文件的遍历,交由迭代器处理,只打印出自己的文件名
// Iterator<FileCompoment> iterator = fileCompoments.iterator();
System.out.format("folerName = {%s}\r\n",fileName);
// while (iterator.hasNext()){
// FileCompoment fileCompoment = iterator.next();
// fileCompoment.print();
// }
}
@Override
public Iterator iterator() {
return new FileIterator(fileCompoments.iterator()); //返回一个文件迭代器
}
public List<FileCompoment> getFileCompoments() {
return fileCompoments;
}
}
迭代器代码:
// 空迭代器
public class NullIterator implements Iterator {
@Override
public boolean hasNext() {
return false;
}
@Override
public Object next() {
return null;
}
}
// 文件迭代器
public class FileIterator implements Iterator<FileCompoment> {
// 由于文件夹是树状结构,其中可能还会包含其他文件夹,所以用栈来装载Iterator
Stack<Iterator> iteratorStack;
public FileIterator(FolderBase folderBase) {
iteratorStack = new Stack<>();
// 最外层的文件夹也要加载
List list = new ArrayList();
list.add(folderBase);
iteratorStack.push(list.iterator());
}
@Override
public boolean hasNext() {
// 如果栈不为空,则获取栈顶迭代器
while (!iteratorStack.isEmpty()) {
Iterator iterator = iteratorStack.peek();
// 如果栈顶迭代器有下一个元素,返回true,否则弹出栈顶迭代器
if (iterator.hasNext()) {
return true;
}else {
iteratorStack.pop();
}
}
return false;
}
@Override
public FileCompoment next() {
Iterator iterator = iteratorStack.peek();
Object fileCompoment =iterator.next();
// 如果迭代器获取的元素是文件夹,把文件夹包含的容器的迭代器装载入栈,迭代完这个文件夹后才弹出继续上一层的迭代
if(fileCompoment instanceof FolderBase){
iteratorStack.push(((FolderBase)fileCompoment).getFileCompoments().iterator());
}
return (FileCompoment) fileCompoment;
}
}
测试代码:
public class Main {
public static void main(String[] args) throws Exception{
FileCompoment folder1 = new FolderBase("folder1");
FileCompoment file1 = new FileBase("file1");
FileCompoment file2 = new FileBase("file2");
FileCompoment folder2 = new FolderBase("folder2");
folder1.addFile(file1);
folder1.addFile(file2);
folder1.addFile(folder2);
FileCompoment file3 = new FileBase("file3");
FileCompoment folder3 = new FolderBase("folder3");
folder2.addFile(file3);
folder2.addFile(folder3);
FileCompoment file4 = new FileBase("file4");
FileCompoment file5 = new FileBase("file4");
folder3.addFile(file4);
folder3.addFile(file5);
Iterator<FileCompoment> iterator = folder1.iterator();
while (iterator.hasNext()){
FileCompoment fileCompoment = iterator.next();
fileCompoment.print();
}
}
}