迭代器模式

一. 复习java提供的迭代器

  1. 在import java.util.Iterator 提供了迭代器接口,该接口被其子类实现并重写抽象方法,主要关注 hashNext(), next(),remove(),方法等
  2. 已ArrayList集合为例,该集合继承AbstractList抽象类,在AbstractList中通过一个内部类,实现了Iterator接口,并从写了抽象方法

AbstractList源码(这就是迭代器模式)

	public Iterator<E> iterator() {
        return new Itr();
    }
    private class Itr implements Iterator<E> {
        /**
         * Index of element to be returned by subsequent call to next.
         */
        int cursor = 0;

        /**
         * Index of element returned by most recent call to next or
         * previous.  Reset to -1 if this element is deleted by a call
         * to remove.
         */
        int lastRet = -1;

        /**
         * The modCount value that the iterator believes that the backing
         * List should have.  If this expectation is violated, the iterator
         * has detected concurrent modification.
         */
        int expectedModCount = modCount;

        public boolean hasNext() {
            return cursor != size();
        }

        public E next() {
            checkForComodification();
            try {
                int i = cursor;
                E next = get(i);
                lastRet = i;
                cursor = i + 1;
                return next;
            } catch (IndexOutOfBoundsException e) {
                checkForComodification();
                throw new NoSuchElementException();
            }
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                AbstractList.this.remove(lastRet);
                if (lastRet < cursor)
                    cursor--;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException e) {
                throw new ConcurrentModificationException();
            }
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

分析AbstractList源码:

  • 获取Iterato: 返回的是实现了Iterator接口的Itr内部类对象
  • hashNext()方法: 判断的是当前下标如果不等于集合长度的话就返回true;如果等于size()时会出现两种情况,当前集合数据为空,或者当前下标的位置等于了集合总长度,如果此时根据下标值去获取集合中的元素时,会抛出空指针异常,因为"下标=size()-1";返回false
  • next()方法: 首先会根据下标位置获取集合中的元素,然后将下标位置累计+1向下一个进行迭代,然后返回
  • 总结: 在集合中使用Iterator迭代器时,如果需要执行next()获取数据,必须要先执行hashNext()去判断元素,并初始化下标位置,在next()获取元素时,会自动将下标加1,向下迭代,复习查看迭代器源码的原因是为了学习迭代,后面会用到,注意在哪个位置进行迭代(有的会在hasnNext()方法中迭代)

二. 迭代器模式概述

是一种行为型设计模式,提供一种方法顺序的访问容器中的各个元素,而又不需要暴露该对象的内部表示(这里的内部表示是不是可以理解为容器的类型?,例如使用数组作为容器,使用List集合作为容器,或者使用Map集合作为容器?迭代器模式是为了解决,自定义容器的时候,或者容器类型不统一的时候使用的?)

迭代器模式角色分析

  • Iterator 迭代器接口import java.util.Iterator,定义了访问遍历,删除元素的抽象方法
  • ConcreteIterator 具体迭代器,持有容器数据,定义了迭代需要的下标位置,实现Iterator接口,根据容器类型的不同重写抽象方法,
  • Aggregate 容器接口: 存放数据的容器的抽象父接口,定义了获取迭代器的抽象方法
  • ConcreteAggregate: 具体容器,实现容器父接口,编写根据数据容器获取迭代器的方法
  • Element 数据父接口,与数据对象实体

三. 案例示例

案例:
遍历展示学院中的系,计算机学院的系在计算机中是以集合存放的,信息学院中的系是已数组存放的

代码示例

  1. 创建实体数据对象"系"对应 Element
//系
class Department{
	private String name; //系的名字
	private String desc; //系的描述
	public Department(String name, String desc) {
		super();
		this.name = name;
		this.desc = desc;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getDesc() {
		return desc;
	}
	public void setDesc(String desc) {
		this.desc = desc;
	}
}
  1. 创建具体迭代器一 “计算机学院迭代器"与"信息学院迭代器” 对应 ConcreteIterator,注意容器类型的不同,hashNext()方法,与next()方法的编写方式
//计算机学院,实现Iterator接口,并重写抽象方法
class ComputerCollegeIterator implements Iterator{
	//1.存放数据的容器(存放者计算机学院的所有系)
	public Department[] departmentArr;
	//2.游标首次的位置(为迭代遍历元素提供)
	public int index = 0;
	
	//构造器对容器赋值
	public ComputerCollegeIterator(Department[] departmentArr) {
		this.departmentArr = departmentArr;
	}
	
	//重写hashNext()方法,获取是否有值
	@Override
	public boolean hasNext() {
		if(index>= departmentArr.length || null == departmentArr[index]) {
			return false;
		}else {
			return true;
		}
	}

	//重写next方法,获取元素,并迭代游标
	@Override
	public Object next() {
		Department department = departmentArr[index];
		index +=1;
		return department;
	}
}
//信息学院迭代器,实现Iterator接口
class InfoCollegeIterator implements Iterator{
	//系容器
	public List<Department> departmentList;
	//游标首次的位置
	public int index = -1;
	
	//构造器对容器数据赋值
	public InfoCollegeIterator(List<Department> departmentList) {
		this.departmentList = departmentList;
	}
	//判断是否有值,重点,如果有值,会迭代游标+1
	@Override
	public boolean hasNext() {
		if(index >= departmentList.size()-1) {
			return false;
		}else {
			index += 1;
			return true;
		}
	}
	//重写next()方法,直接get()根据下标位置返回
	@Override
	public Object next() {
		return departmentList.get(index);
	}
}
  1. 创建容器父接口对应 Aggregate,重点是获取迭代器方法
interface College{
	//添加系
	public void addDepartment(Department department);
	//获取迭代器
	public Iterator createIterator();
}
  1. 创建具体容器,“计算机学院”,“信息学院”,不同容器中存放数据的容器类型不同
//计算机学院
class ComputerCollege implements College{
	//存放计算机系的容器是数组
	public Department[] departmentArr;
	//向容器中添加数据"系"的下标位置
	public int numOfDepartment = 0; 
	
	//通过构造器初始化存放系的容器大小
	public ComputerCollege(int size) {
		departmentArr = new Department[size];
	}
	//想容器中添加数据(系)
	@Override
	public void addDepartment(Department department) {
		departmentArr[numOfDepartment] = department;
		numOfDepartment +=1;
	}
	//根据容器的不同获取对应的具体迭代器
	@Override
	public Iterator createIterator() {
		return new ComputerCollegeIterator(departmentArr);
	}
}
//信息学院
class InfoCollege implements College{
	//存放计算机系的容器是数组
	public List<Department> departmentList = new ArrayList<>();
	//向容器中添加数据"系"的下标位置
	public int numOfDepartment = 0; 
	
	@Override
	public void addDepartment(Department department) {
		departmentList.add(department);
		numOfDepartment +=1;
	}

	@Override
	public Iterator createIterator() {
		return new InfoCollegeIterator(departmentList);
	}
}
  1. 对应客户端的交互层(为了方便客户端调用加的,跟此处的的设计模式没有关系)
//对应客户端的交互层
class OutPutImpl{
	
	//存放学院的容器
	public List<College> collegeList;
	
	//通过构造器初始化赋值学院
	public OutPutImpl(List<College> collegeList) {
		this.collegeList = collegeList;
	}
	
	//遍历输出学院,学院与学院总保存的系的信息
	public void printCollege() {
		Iterator<College> iterator = collegeList.iterator();
		while(iterator.hasNext()) {
			//拿到学院对象数据
			College college = iterator.next();
			
			printDepartment(college.createIterator());
		}
	}
	
	//遍历输出指定学院中的系信息(Iterator对应的是具体学院)
	public void printDepartment(Iterator iterator) {
		while(iterator.hasNext()) {
			Department department = (Department) iterator.next();
			System.out.println(department.getName());
		}
	}
}
  1. 调用测试
public static void main(String[]args) {
    	//创建学院集合
    	List<College> collegeList = new ArrayList<College>();
    	//创建计算机学院
    	ComputerCollege computerCollege = new ComputerCollege(10);
    	//将计算机学院放入集合中
    	collegeList.add(computerCollege);
    	
    	//创建"通信工程"系
    	Department de = new Department("通信工程","通信工程系描述");
    	
    	//将"通信工程系"放入计算机学院中
    	computerCollege.addDepartment(de);
    	
    	//创建交互层对象
    	OutPutImpl out = new OutPutImpl(collegeList);
    	//输出学院与学院中的系的信息
    	out.printCollege();
    }
  1. 流程图(不是UML)
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值