您的位置:首页 > 其它

设计模式——迭代器模式

2018-01-16 16:24 225 查看

作者:云都小生

推荐学习资源

史上最全的设计模式导学目录

十分推荐!

概述

迭代器模式是比较容易理解,且使用频率非常高的一种设计模式,它的本质是实现了数据聚合对象的存储与遍历的解耦,使数据聚合不会暴露在数据操作方法面前。

在现实的开发中,我们经常会碰到一种情况,我们需要存储许多的对象,有时候需要对这些对象进行遍历。

一般去设计的时候,都是把存储和遍历两种功能放到同一个类中,但是这样会产生许多的问题。

首先,违背了“单一职责”,每个类/方法都应该只负责一件事,聚合类既负责存储又负责遍历。

其次,违背了“封装性”,你想想看,如果存储数据和操作数据的方法放在同一个类,那么存储的数据就会都暴露出来。

设计中的角色

通常许多编程语言的标准库,都为我们实现了迭代器,但是为了了解迭代器的具体细节,所以我也学着去实现一下。先了解一下整个设计的框架。

抽象聚合类:该抽象类封装了一般聚合类都需要的属性和方法,它需要存储很多元素对象,所以需要内置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:云都小生
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息