设计模式学习-迭代器模式

迭代器模式

迭代器模式一般设计用来对一个容器对象进行遍历,通过引入一个迭代器,将容器的存储功能和遍历功能进行分离,容器只有存储功能,遍历功能由迭代器来完成,进行了职责的分离,更加符合单一职责原则。
在使用迭代器模式的过程中,除了功能的分离,还有另一个好处:当一个容器接口有不同的实现的时候,为每一个实现提供了一个统一的遍历接口,这样一方面具体实现不需要对外暴露它的内部结构,另一方面调用方也不用关系实现类内部结构的变化,只要关注它的遍历方法就可以了,这也是解耦的好处。

定义

提供一种方法顺序访问一个聚合对象中的各个元素,而又不用暴露该对象的内部表示。

结构

迭代器模式中包含了容器和迭代器两个方面的层次结构,具体结构如下:

  • Iterator抽象迭代器,定义了迭代器的接口和遍历的方法
  • ConcreteIterator具体迭代器。迭代器接口的实现类,实现了迭代器中的所有方法
  • Aggregate抽象聚合(容器)类。容器接口,定义了存储和获取迭代器的方法
  • ConcreteAggregate具体聚合(容器)类。实现了容器接口,实现了具体存储和获取迭代器的方法
    image

实例

参照上面类图,编写一个简单的容器和迭代器的实现。在设计迭代器接口的时候,接口方法的设计特别重要,一方面要考虑方法的适用性,能够提供各种重要的遍历方案,另一方面又不能有太多的抽象方法。在下面的例子中,只有简单的next()和hasNext()方法。

package iterator;

class Fruit {
	
	public Fruit(String name, String color) {
		super();
		this.name = name;
		this.color = color;
	}

	private String name; 
	
	private String color;

	@Override
	public String toString() {
		return "Fruit [name=" + name + ", color=" + color + "]";
	}
	
}
package iterator;

interface FruitIterator {

	boolean hasNext();
	
	Fruit next();
}

package iterator;

public interface FruitAggregate {
	
	void addFruit(Fruit fruit);

	FruitIterator iterator();
}

package iterator;

import java.util.List;

public class FruitIteratorList implements FruitIterator {

	private List<Fruit> fruitList;
	
	private int now;
	
	
	public FruitIteratorList(FruitAggregateList fruitAggregateList) {
		this.fruitList = fruitAggregateList.fruitList;
	}

	@Override
	public boolean hasNext() {
		return now < fruitList.size();
	}

	@Override
	public Fruit next() {
		return fruitList.get(now++);
	}

}

package iterator;

import java.util.List;

public class FruitIteratorList implements FruitIterator {

	private List<Fruit> fruitList;
	
	private int now;
	
	
	public FruitIteratorList(FruitAggregateList fruitAggregateList) {
		this.fruitList = fruitAggregateList.fruitList;
	}

	@Override
	public boolean hasNext() {
		return now < fruitList.size();
	}

	@Override
	public Fruit next() {
		return fruitList.get(now++);
	}

}

package iterator;

public class Test {

	public static void main(String[] args) {
		Fruit apple = new Fruit("苹果", "红色");
		Fruit pear = new Fruit("梨", "青色");
		
		FruitAggregate fruits = new FruitAggregateList();
		
		fruits.addFruit(apple);
		fruits.addFruit(pear);
		
		FruitIterator iterator = fruits.iterator();
		while (iterator.hasNext()) {
			System.out.println(iterator.next());
		}
	}
}

应用

关于迭代器模式,最常见的便是java的集合部分。因为具体迭代器的实现跟关联的具体容器类有关,因此不同实现的容器类应该有不同的迭代器。比如上面的实例中,FruitIteratorList是通过List实现自己的存储功能的,那么它的迭代器必定是在List的基础上实现的,迭代器的方法都与List中的方法有关。因此,不同的容器有不同的迭代器实现。
Java中,是通过内部类来实现迭代器的。无论是存储结构还是迭代器的实现,不同的Collection实现类内部都是不一样的,而且这些都是不需要对外暴露的内容,因此我们只需要知道迭代器有哪些方法,并且怎么获取迭代器就可以了。

public interface List<E> extends Collection<E> {
...
Iterator<E> iterator();
}

public class ArrayList<E> extends AbstractList<E> {
...
public Iterator<E> iterator() {
    return new Itr();
}
...
private class Itr implements Iterator<E> {
    ...
}
..
}

优缺点

优点

  • 将容器类的存储功能和遍历功能相分离
  • 不需要对外暴露容器内部具体的实现
  • 提供统一的迭代器方法,对于容器的不同实现提供了规范
  • 引入抽象设计,对于新的容器只需要引入新的迭代器,符合开闭原则

缺点

  • 增加新的容器就需要增加新的迭代器,增加了代码的复杂性
  • 抽象迭代器设计比较麻烦

适用场景

  • 提供了一个容器对象但是无须了解内部实现
  • 容器具有对重实现方式或者容器需要多种遍历方式
  • 为不同的容器结构提供一个遍历的统一方法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值