以展示学校院系结构引出迭代器模式
这次的案例就是之前学习组合模式的案例,但其中也有些不同。
在一个页面中展示出学校的院系组成,一个学校有多个学院, 一个学院有多个系。如图:
传统思路

将学院看做是学校的子类,系是学院的子类,这样实际上是站在组织大小来进行分层次的。
实际上我们的要求是:在一个页面中展示出学校的院系组成,一个学校有多个学院,一个学院有多个院系,因此这种方案,不能很好实现的遍历的操作。
如果我们的集合元素是用不同的方式实现的,有数组,还有 java 的集合类,或者还有其他方式,当客户端要遍历这些集合元素的时候就要使用多种遍历方式,而且还会暴露元素的内部结构,可以考虑使用迭代器模式解决。
迭代器模式,提供一种遍历集合元素的统一接口,用一致的方法遍历集合元素,不需要知道集合对象的底层表示,即:不暴露其内部的结构。
属于行为型模式。
Iterator接口
- public interface Iterator
{ -
- boolean hasNext();
-
- E next();
-
- default void remove() {
- throw new UnsupportedOperationException("remove");
- }
-
- default void forEachRemaining(Consumer super E> action) {
- Objects.requireNonNull(action);
- while (hasNext())
- action.accept(next());
- }
- }

实现计算机学院和信息管理学院的两个迭代器,因为它们记录院系的集合不同,需要分别实现迭代器。
- public class ComputerIterator implements Iterator {
- // 以数组方式存储--> 系
- private Department[] departments;
- // 下标位置
- int index;
-
- public ComputerIterator(Department[] departments) {
- this.departments = departments;
- }
-
- // 判断后面是否还有元素
- public boolean hasNext() {
- if(index >= departments.length || departments[index] == null){
- return false;
- }
- return true;
- }
-
- // 获取下一个元素
- public Object next() {
- return departments[index++];
- }
-
- // 删除方法:空实现
- public void remove() {
-
- }
- }
- public class InfoManagerIterator implements Iterator {
-
- private List
list = new ArrayList(); - private int index;
-
- public InfoManagerIterator(List
list) { - this.list = list;
- }
-
- // 判断后面是否还有元素
- public boolean hasNext() {
- if(index >= list.size() || list.get(index) == null){
- return false;
- }
- return true;
- }
-
- // 获取下一个元素
- public Object next() {
- return list.get(index++);
- }
-
- // 删除方法:空实现
- public void remove() {
-
- }
- }
学院接口及其实现类
- public interface College {
- //获取学院名字
- public String getCollegeName();
- //添加院系
- public void addDepartment(Department department);
- //获取迭代器
- public Iterator getIterator();
- }
- public class ComputerCollege implements College{
-
- private Department[] departments;
- //记录数组的对象数
- int num = 4;
-
- public ComputerCollege(){
- departments = new Department[10];
- departments[0] = new Department("计科","计算机科学与技术");
- departments[1] = new Department("软工","软件工程");
- departments[2] = new Department("网工","网络工程");
- departments[3] = new Department("大数据","大数据");
- }
-
- public String getCollegeName() {
- return "计算机学院";
- }
-
- public void addDepartment(Department department) {
- departments[num++] = department;
- }
-
- public Iterator getIterator() {
- return new ComputerIterator(departments);
- }
- }
- public class InfoManagerCollege implements College{
-
- private List
list; -
- public InfoManagerCollege(){
- list = new ArrayList
(); - list.add(new Department("信管","信息管理"));
- list.add(new Department("新计","信息计算"));
- }
-
- public String getCollegeName() {
- return "信息管理学院";
- }
-
- public void addDepartment(Department department) {
- list.add(department);
- }
-
- public Iterator getIterator() {
- return new InfoManagerIterator(list);
- }
- }
打印学院及其院系的类
- public class OutputCollege {
-
- private List
colleges; -
- public OutputCollege(){
- colleges = new ArrayList
(); - colleges.add(new ComputerCollege());
- colleges.add(new InfoManagerCollege());
- }
-
- // 打印学院以及下面的院系
- public void getCollegeAllDeparment(){
- Iterator
iterator = colleges.iterator(); - while (iterator.hasNext()){
- //获取到学院
- College college = iterator.next();
- System.out.println("-----" + college.getCollegeName() + "-----");
- //获取学院的迭代器
- //计算机学院用的数组存储,信息管理用列表存储,通过迭代器可统一使用
- Iterator collegeIterator = college.getIterator();
- while (collegeIterator.hasNext()){
- //获取到院系
- Department department = (Department) collegeIterator.next();
- System.out.println(department.getName() + " : " + department.getDescription());
- }
- }
- }
- }
测试
- public class Client {
- public static void main(String[] args) {
- OutputCollege outputCollege = new OutputCollege();
- outputCollege.getCollegeAllDeparment();
- }
- }
结果
-----计算机学院-----
计科 : 计算机科学与技术
软工 : 软件工程
网工 : 网络工程
大数据 : 大数据
-----信息管理学院-----
信管 : 信息管理
新计 : 信息计算
ArrayList实现了List接口
- public class ArrayList
extends AbstractList - implements List
, RandomAccess, Cloneable, java.io.Serializable
List 充当了聚合接口,含有一个 iterator() 方法,返回一个迭代器对象
- public interface List
extends Collection { -
- Iterator
iterator(); - }
ArrayList 是实现聚合接口 List 的子类,实现了iterator()
Itr 作为 ArrayList 内部类,充当具体实现迭代器 Iterator 的类
- public Iterator
iterator() { - return new Itr();
- }
-
- private class Itr implements Iterator
{ - int cursor; // index of next element to return
- int lastRet = -1; // index of last element returned; -1 if no such
- int expectedModCount = modCount;
-
- public boolean hasNext() {
- return cursor != size;
- }
-
- @SuppressWarnings("unchecked")
- public E next() {
- checkForComodification();
- int i = cursor;
- if (i >= size)
- throw new NoSuchElementException();
- Object[] elementData = ArrayList.this.elementData;
- if (i >= elementData.length)
- throw new ConcurrentModificationException();
- cursor = i + 1;
- return (E) elementData[lastRet = i];
- }
-
- public void remove() {
- if (lastRet < 0)
- throw new IllegalStateException();
- checkForComodification();
-
- try {
- ArrayList.this.remove(lastRet);
- cursor = lastRet;
- lastRet = -1;
- expectedModCount = modCount;
- } catch (IndexOutOfBoundsException ex) {
- throw new ConcurrentModificationException();
- }
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public void forEachRemaining(Consumer super E> consumer) {
- Objects.requireNonNull(consumer);
- final int size = ArrayList.this.size;
- int i = cursor;
- if (i >= size) {
- return;
- }
- final Object[] elementData = ArrayList.this.elementData;
- if (i >= elementData.length) {
- throw new ConcurrentModificationException();
- }
- while (i != size && modCount == expectedModCount) {
- consumer.accept((E) elementData[i++]);
- }
- // update once at end of iteration to reduce heap write traffic
- cursor = i;
- lastRet = i - 1;
- checkForComodification();
- }
-
- final void checkForComodification() {
- if (modCount != expectedModCount)
- throw new ConcurrentModificationException();
- }
- }
具体关系为:

迭代器模式解决了不同集合(ArrayList ,LinkedList) 统一遍历问题
1)提供一个统一的方法遍历对象,客户不用再考虑聚合的类型,使用一种方法就可以遍历对象了。
2)隐藏了聚合的内部结构,客户端要遍历聚合的时候只能取到迭代器,而不会知道聚合的具体组成。
3)提供了一种设计思想,就是一个类应该只有一个引起变化的原因(叫做单一责任原则)。在聚合类中,我们把迭代器分开,就是要把管理对象集合和遍历对象集合的责任分开,这样一来集合改变的话,只影响到聚合对象。 而如果遍历方式改变的话,只影响到了迭代器。
4)当要展示一组相似对象,或者遍历一组相同对象时使用,适合使用迭代器模式
每个聚合对象都要一个迭代器,会生成多个迭代器不好管理类