程序员必知的23种设计模式之迭代器模式

1. 模式引出–打印需求

系统需要几个人员的集合类,类中底层实现有使用数组,列表,或者是集合,现在需要编写程序,可以遍历所有人员。

  1. 有一个ArrayPeoples类和ListPeoples类,ArrayPeoples类中People的集合为数组、ListPeoples类中People的集合为列表
  2. People类为集合元素
  3. 需要一起遍历ArrayPeoples类和ListPeoples类中的集合
1.1 传统方案
  1. 可以在所有类的外部获取集合后判断类型然后遍历

  2. 可以在类内部定义一个遍历方法,提供给外部调用

1.2 传统的方式的问题分析
  1. 每个人员类中的方法不一定相同,不能做到用统一的方式遍历有数据
  2. 调用麻烦,实现也麻烦
  3. 解决方案:迭代器模式
2. 迭代器模式基本介绍
  1. 迭代器模式(Iterator Pattern)是常用的设计模式,属于行为型模式

  2. 如果我们的集合元素是用不同的方式实现的,有数组,还有java的集合类,或者还有其他方式,当客户端要遍历这些集合元素的时候就要使用多种遍历方式,而且还会暴露元素的内部结构,可以考虑使用迭代器模式解决。

  3. 迭代器模式,提供一种遍历集合元素的统一接口,用一致的方法遍历集合元素,不需要知道集合对象的底层表示,即:不暴露其内部的结构。

2.1 迭代器模式的原理类图

在这里插入图片描述

对原理类图的说明即(迭代器模式的角色及职责)

  1. Iterator :迭代器接口, 是系统提供,含义hastNext, next, remove
  2. ConcreteIterator :具体的迭代器类,管理迭代
  3. Aggregate :-个统-的聚合聚合接口,将客户端和具体聚合解耦
  4. Concretelggreage :具体的聚合持有对象集合
3. 方案修改

UML类图

在这里插入图片描述
Iterator.java

// java自带,无需创建

Peoples.java

// 聚合对象的接口
public interface Peoples {
	Iterator<Peoples> getIterator();
}

People.java

// 集合元素
public class People {
	private String name;
	private int age;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "People [name=" + name + ", age=" + age + "]";
	}

	public People(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

}

ArrayPeoples.java

// 具体聚合类
public class ArrayPeoples implements Peoples{
	private People[] peoples = new People[10];

	public ArrayPeoples() {
		for (int i = 0; i < 5; i++) {
			peoples[i] = new People("echoArray" + i, i * i);
		}
	}

	public Iterator getIterator() {
		return new ArrayIterator(peoples);
	}

}

ListPeoples.java

// 具体聚合类
public class ListPeoples implements Peoples{
	private List<People> peoples = new ArrayList<People>();
	
	public ListPeoples() {
		peoples.add(new People("echolist", 1));
		peoples.add(new People("echolist", 2));
		peoples.add(new People("echolist", 3));
		peoples.add(new People("echolist", 4));
	}
	
	
	public Iterator getIterator() {
		return new ListIterator(peoples);
	}
	
}

ListIterator.java

// 具体迭代器
public class ListIterator implements Iterator<People> {

	private List<People> peoples;
	private int foot = 0;

	public ListIterator(List<People> peoples) {
		this.peoples = peoples;
	}

	@Override
	public boolean hasNext() {
		return foot < peoples.size();
	}

	@Override
	public People next() {
		People people = peoples.get(foot);
		foot++;
		return people;
	}

}

ArrayIterator.java

// 具体迭代器
public class ArrayIterator implements Iterator<People> {

	private People[] peoples;
	private int foot = 0;

	public ArrayIterator(People[] peoples) {
		this.peoples = peoples;
	}

	@Override
	public boolean hasNext() {
		return foot < peoples.length && peoples[foot] != null;

	}

	@Override
	public People next() {
		People people = peoples[foot];
		foot++;
		return people;
	}

}

PrintPeoples.java

// 遍历管理类
public class PrintPeoples {

	private List<Peoples> list = new ArrayList<Peoples>();

	public void addPeopels(Peoples p) {
		list.add(p);
	}

	public void print() {
		Iterator<Peoples> iterator = list.iterator();
		while (iterator.hasNext()) {
			Peoples peoples = iterator.next();
			print(peoples);
		}
	}

	public void print(Peoples peoples) {
		Iterator<Peoples> iterator = peoples.getIterator();
		while (iterator.hasNext()) {
			System.out.println(iterator.next());
		}
	}
}

测试Main.java

public class Main {
	public static void main(String[] args) {
		ArrayPeoples arrayPeoples = new ArrayPeoples();
		ListPeoples listPeoples = new ListPeoples();
		PrintPeoples printPeoples = new PrintPeoples();
		printPeoples.addPeopels(arrayPeoples);
		printPeoples.addPeopels(listPeoples);
		printPeoples.print();
		
	}
}

输出结果

在这里插入图片描述

4. 迭代器模式在JDK1.8-ArrayList集合中的应用

在JDK1.8的ArrayList源码中,可以看到ArrayList这个类实现的接口中有一个叫List的接口

public class ArrayList<E> ...
        implements List<E>, ...
...

追到List接口中瞧一瞧

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

可以发现其中定义了一个Iterator<E> iterator()的方法,该方法返回一个迭代器

回到ArrayList类中,可以看到iterator()方法得到了实现的

public class ArrayList<E> ...
    implements List<E>, ...
{
    ...
    public Iterator<E> iterator() {
        return new Itr();
    }
    ...
}

可以看出,ArrayList的获取迭代器方法返回一个Itr对象,继续追Itr的位置

public class ArrayList<E> ...
    implements List<E>, ...
    ...
    private class Itr implements Iterator<E> {
    ...
    }
    ...
}

可以看出该对象实现了Iterator的接口,即是一个具体的迭代器,由于该类是定义为Arraylist的内部类,所以ArrayList存储的数据可以共享,该迭代器可以直接拿到ArrayList的数据进行遍历操作

public class ArrayList<E> ...
    implements List<E>, ...
    ...
    transient Object[] elementData; // 存储的数据
    ...
}

可以看出,ArrayList类似于上例的聚合类,包含了需要遍历的数据实现了获取迭代器接口的方法

Itr类则类似于上例的具体迭代器类,实现了Iterator接口,利用ArrayList类中的数据进行遍历操作

4.1 总结分析
  1. 内部类Itr 充当具体实现迭代器Iterator 的类, 作为ArrayList 内部类
  2. List 就是充当了聚合接口,含有一个iterator() 方法,返回一个迭代器对象
  3. ArrayList 是实现聚合接口List 的子类,实现了iterator()
  4. Iterator 接口系统提供
  5. 迭代器模式解决了 不同集合(ArrayList ,LinkedList) 统一遍历问题
5. 迭代器模式的注意事项和细节
5.1 优点
  1. 提供一个统一的方法遍历对象,客户不用再考虑聚合的类型,使用一种方法就可以遍历对象了。

  2. 隐藏了聚合的内部结构,客户端要遍历聚合的时候只能取到迭代器,而不会知道聚合的具体组成。

  3. 提供了一种设计思想,就是一个类应该只有一个引起变化的原因(叫做单一责任原则)。在聚合类中,我们把迭代器分开,就是要把管理对象集合和遍历对象集合的责任分开,这样一来集合改变的话,只影响到聚合对象。而如果遍历方式改变的话,只影响到了迭代器。

  4. 当要展示一组相似对象,或者遍历一组相同对象时使用, 适合使用迭代器模式

5.2 缺点
  1. 每个聚合对象都要一个迭代器,会生成多个迭代器不好管理类
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值