1.概述
迭代器模式(Iterator Pattern)提供了一种方法访问一个容器对象中各个元素,而又不暴露该对象的内部细节。迭代器模式用于访问集合中的元素而不需要知道集合底层的数据形式。在JAVA语言中,迭代器模式已经成为其中不可缺少的一部分,主要的接口就是Iterator,所有关于集合元素(Collection集合类型、Set类型等)的访问都可通过该接口来实现。本文将详细解释迭代器的原理以及使用方式。
2.原理及使用
2.1 原理
迭代器模式的UML类图如下所示:
上述类图主要包含四个角色:抽象迭代器角色(Iterator)、具体迭代器角色(ConcreteIterator)、抽象集合角色(Aggregate)、具体集合角色(ConcreteAggregate)。具体解释如下:
抽象迭代器角色(Iterator):定义访问和遍历元素的接口,通常包含next()、hasNext()等方法;
具体迭代器角色(ConcreteIterator):是抽象迭代器的具体实现,实现具体的遍历方法等;
抽象集合角色(Aggregate):定义创建迭代器对象的接口,部分可能会有添加、删除等方法;
具体集合角色(ConcreteAggregate):实现抽象集合角色,返回迭代器实例。
2.2 案例
有个停车场,现在需要定义一个迭代器,遍历停车场中的所有车辆。
按照迭代器模式,画出UML类图如下:
编码如下:
public interface Iterator {
Car first();
Car next();
boolean hasNext();
}
public class CarIterator implements Iterator {
private List<Car> list = new ArrayList<>();
/**
* 当前元素位置
*/
private int position;
public CarIterator(List<Car> list) {
this.list = list;
}
@Override
public Car first() {
if (list.size() > 0) {
return list.get(0);
}
return null;
}
@Override
public Car next() {
if (position < list.size()) {
Car car = list.get(position);
position++;
return car;
}
return null;
}
@Override
public boolean hasNext() {
return position < list.size();
}
}
public interface Aggregate {
Iterator createIterator();
void addCar(Car car);
void remove(Car car);
}
public class CarAggregate implements Aggregate {
private List<Car> list = new ArrayList<>();
public CarAggregate(List<Car> list) {
this.list = list;
}
@Override
public Iterator createIterator() {
return new CarIterator(list);
}
@Override
public void addCar(Car car) {
list.add(car);
}
@Override
public void remove(Car car) {
list.remove(car);
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Car {
/**
* 颜色
*/
private String color;
/**
* 名称
*/
private String name;
/**
* 品牌
*/
private String brand;
/**
* 车牌
*/
private String plate;
public void print() {
System.out.println("车辆颜色:"+color +",名称:"+name + ",品牌"+brand + ",车牌:"+plate);
}
}
public class Client {
public static void main(String[] args) {
List<Car> cars = new ArrayList<>();
cars.add(new Car("红色","宝马","C260L","浙A88888"));
cars.add(new Car("白色","大众","途观","浙A0001"));
cars.add(new Car("黑色","路虎","陆地巡洋舰","浙A99999"));
cars.add(new Car("蓝色","沃尔沃","C50","浙A66666"));
CarIterator carIterator = new CarIterator(cars);
while (carIterator.hasNext()) {
Car car = carIterator.next();
car.print();
}
}
}
运行结果如下:
2.3 源码分析
在JDK源码中,定义了一个迭代器类Iterator,用于List集合或Set的遍历,类图如下:
2.4 优点和缺点
2.4.1 优点
1.提供了一个统一的方法遍历对象,客户端不需要考虑集合的类型,使用一种方法遍历即可;
2.隐藏集合的内部结构,不需要知道集合的具体组成,通过获取迭代器即可遍历;
3.迭代器与具体的管理对象分离,管理对象集合变更,只影响聚合对象,遍历方式发生改变,则只会影响迭代器,符合单一职责原则。
2.4.2 缺点
1.每个聚合对象都需要不同的迭代器,可能导致类爆炸;
2.在一定程度上增加了系统复杂性。
3.小结
1.迭代器模式的使用场景主要是为聚合对象提供遍历时,且针对不同的聚合对象,遍历方式不同;
2.迭代器模式能够降低对聚合类的细节了解,通过迭代器访问即可;
3.在JAVA语言中,迭代器已经被多处运用(Iterator接口);
4.目前各个语言基本上都已经将迭代器模式整合其中,成为基础一部分,手写迭代器的场景相对较少。
4.参考文献
1.《设计模式之禅》-秦小波著
2.《大话设计模式》-程杰著
3.https://www.bilibili.com/video/BV1G4411c7N4-尚硅谷设计模式
4.https://www.runoob.com/design-pattern/observer-pattern.html