作者:云都小生
推荐学习资源
史上最全的设计模式导学目录
十分推荐!
概述
迭代器模式是比较容易理解,且使用频率非常高的一种设计模式,它的本质是 实现了数据聚合对象的存储与遍历的解耦,使数据聚合不会暴露在数据操作方法面前。
在现实的开发中,我们经常会碰到一种情况,我们需要存储许多的对象,有时候需要对这些对象进行遍历。
一般去设计的时候,都是把存储和遍历两种功能放到同一个类中,但是这样会产生许多的问题。
首先,违背了“单一职责”,每个类/方法都应该只负责一件事,聚合类既负责存储又负责遍历。
其次,违背了“封装性”,你想想看,如果存储数据和操作数据的方法放在同一个类,那么存储的数据就会都暴露出来。
设计中的角色
通常许多编程语言的标准库,都为我们实现了迭代器,但是为了了解迭代器的具体细节,所以我也学着去实现一下。先了解一下整个设计的框架。
抽象聚合类:该抽象类封装了一般聚合类都需要的属性和方法,它需要存储很多元素对象,所以需要内置List。它需要创建自己对应的一个迭代器,所以需要一个方法createIterator()。
具体聚合类:继承了抽象聚合类,实现了抽象聚合类的抽象方法,具体聚合类可以生成自己相对应的迭代器。
抽象迭代器:声明了迭代器对聚合数据的遍历方法,
定义了共同的属性。
具体迭代器:继承了抽象迭代器类,实现了具体的遍历方法。
案例1——独自实现迭代器
通过查看一些参考手册,我们知道迭代器和聚合对象通常需要一些什么属性和方法,利用抽象类封装起来。
import java.util.*;
//抽象聚合类
public abstract class AbstractAggregated {
//该聚合数据只有子类能看到,良好的封装
protected List<Object> objects = new ArrayList<Object>();
public AbstractAggregated(List objects)
{
this.objects = objects;
}
//增加元素
public void addObject(Object obj) {
this.objects.add(obj);
}
//删除元素
public void removeObject(Object obj) {
this.objects.remove(obj);
}
//返回List
public List getObjects() {
return this.objects;
}
//声明创建迭代器对象的抽象工厂方法
public abstract AbstractIterator createIterator();
}
import java.util.List;
//具体聚合类
public class TestAggregated extends AbstractAggregated {
public TestAggregated(List objects) {
super(objects);
}
//实现创建迭代器对象的具体工厂方法
public AbstractIterator createIterator() {
return new TestIterator(this);
}
}
public abstract class AbstractIterator {
public abstract void next(); //移至下一个元素
public abstract boolean isLast(); //判断是否为最后一个元素
public abstract void previous(); //移至上一个元素
public abstract boolean isFirst(); //判断是否为第一个元素
public abstract Object getNextItem(); //获取下一个元素
public abstract Object getPreviousItem(); //获取上一个元素
}
import java.util.*;
public class TestIterator extends AbstractIterator {
private TestAggregated testAggregated;
private List objects;
private int cursor1;
private int cursor2;
public TestIterator(TestAggregated testAggregated) {
this.testAggregated = testAggregated;
this.objects = testAggregated.objects;
if(objects.isEmpty())
{
cursor1 = -1;
cursor2 = -1;
}
else
{
cursor1 = 0;
cursor2 = objects.size()-1;
}
}
//把正序游标调整到下一个元素
public void next() {
if(cursor1 < objects.size())
{
cursor1++;
}
}
//判断是否是最后一个元素
public boolean isLast() {
return (cursor1 == objects.size());
}
//把逆序的游标调整到上一个元素
public void previous() {
if(cursor2 > -1)
{
cursor2--;
}
}
//判断是否是第一个元素
public boolean isFirst() {
return (cursor2 == -1);
}
//获取下一个元素
public Object getNextItem() {
return objects.get(cursor1);
}
//获取上一个元素
public Object getPreviousItem() {
return objects.get(cursor2);
}
}
//客户端测试类
public class Client {
public static void main(String[] args) {
List objects = new ArrayList();
objects.add("A");
objects.add("B");
objects.add("C");
objects.add("D");
AbstractAggregated list = new TestAggregated(objects);
AbstractIterator iterator = list.createIterator();
System.out.println("正向遍历:");
while(!iterator.isLast())
{
System.out.print(iterator.getNextItem() + ",");
iterator.next();
}
System.out.println();
System.out.println("-----------------------------");
System.out.println("逆向遍历:");
while(!iterator.isFirst())
{
System.out.print(iterator.getPreviousItem() + ",");
iterator.previous();
}
}
}
案例2——利用IDK内置的迭代器
我们可以直接用标准库里面的Collection和Iterator,来进行遍历。
import java.util.*;
public class Client {
public static void main(String[] args) {
Collection objects = new ArrayList();
objects.add("A");
objects.add("B");
objects.add("C");
objects.add("D");
traverse(objects);
}
public static void traverse(Collection c)
{
Iterator i = c.iterator();
while(i.hasNext())
{
System.out.println(i.next().toString());
}
}
}
总结
迭代器模式本质上是聚合类与迭代类之间的解耦,简化了聚合类,引入了迭代器。并且,我们还可以在掘和对象自定义多种遍历方法,符合开闭原则,可以增加新的遍历方式。
2018/1/16 16:21:48 @Author:云都小生