• 尚硅谷设计模式(十九)迭代器模式


    以展示学校院系结构引出迭代器模式

    这次的案例就是之前学习组合模式的案例,但其中也有些不同。

    在一个页面中展示出学校的院系组成,一个学校有多个学院, 一个学院有多个系。如图:

    传统思路 

    将学院看做是学校的子类,系是学院的子类,这样实际上是站在组织大小来进行分层次的。

    实际上我们的要求是:在一个页面中展示出学校的院系组成,一个学校有多个学院,一个学院有多个院系,因此这种方案,不能很好实现的遍历的操作。

    一、迭代器模式

    1、基本介绍

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

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

    属于行为型模式

    Iterator接口

    1. public interface Iterator {
    2. boolean hasNext();
    3. E next();
    4. default void remove() {
    5. throw new UnsupportedOperationException("remove");
    6. }
    7. default void forEachRemaining(Consumersuper E> action) {
    8. Objects.requireNonNull(action);
    9. while (hasNext())
    10. action.accept(next());
    11. }
    12. }

    • Iterator:迭代器接口,系统提供
    • ConcreteIterator:具体的迭代器类,管理迭代
    • Aggregate:一个统一的聚合接口,将客户端和具体聚合解耦
    • ConcreteAggreage:具体的聚合持有对象集合,并提供一个方法,返回一个迭代器,该迭代器可以正确遍历集合
    • Client:客户端,通过  Iterator   和 Aggregate  依赖子类

    2、代码实现

    实现计算机学院和信息管理学院的两个迭代器,因为它们记录院系的集合不同,需要分别实现迭代器。

    1. public class ComputerIterator implements Iterator {
    2. // 以数组方式存储--> 系
    3. private Department[] departments;
    4. // 下标位置
    5. int index;
    6. public ComputerIterator(Department[] departments) {
    7. this.departments = departments;
    8. }
    9. // 判断后面是否还有元素
    10. public boolean hasNext() {
    11. if(index >= departments.length || departments[index] == null){
    12. return false;
    13. }
    14. return true;
    15. }
    16. // 获取下一个元素
    17. public Object next() {
    18. return departments[index++];
    19. }
    20. // 删除方法:空实现
    21. public void remove() {
    22. }
    23. }
    1. public class InfoManagerIterator implements Iterator {
    2. private List list = new ArrayList();
    3. private int index;
    4. public InfoManagerIterator(List list) {
    5. this.list = list;
    6. }
    7. // 判断后面是否还有元素
    8. public boolean hasNext() {
    9. if(index >= list.size() || list.get(index) == null){
    10. return false;
    11. }
    12. return true;
    13. }
    14. // 获取下一个元素
    15. public Object next() {
    16. return list.get(index++);
    17. }
    18. // 删除方法:空实现
    19. public void remove() {
    20. }
    21. }

    学院接口及其实现类

    1. public interface College {
    2. //获取学院名字
    3. public String getCollegeName();
    4. //添加院系
    5. public void addDepartment(Department department);
    6. //获取迭代器
    7. public Iterator getIterator();
    8. }
    1. public class ComputerCollege implements College{
    2. private Department[] departments;
    3. //记录数组的对象数
    4. int num = 4;
    5. public ComputerCollege(){
    6. departments = new Department[10];
    7. departments[0] = new Department("计科","计算机科学与技术");
    8. departments[1] = new Department("软工","软件工程");
    9. departments[2] = new Department("网工","网络工程");
    10. departments[3] = new Department("大数据","大数据");
    11. }
    12. public String getCollegeName() {
    13. return "计算机学院";
    14. }
    15. public void addDepartment(Department department) {
    16. departments[num++] = department;
    17. }
    18. public Iterator getIterator() {
    19. return new ComputerIterator(departments);
    20. }
    21. }
    1. public class InfoManagerCollege implements College{
    2. private List list;
    3. public InfoManagerCollege(){
    4. list = new ArrayList();
    5. list.add(new Department("信管","信息管理"));
    6. list.add(new Department("新计","信息计算"));
    7. }
    8. public String getCollegeName() {
    9. return "信息管理学院";
    10. }
    11. public void addDepartment(Department department) {
    12. list.add(department);
    13. }
    14. public Iterator getIterator() {
    15. return new InfoManagerIterator(list);
    16. }
    17. }

    打印学院及其院系的类

    1. public class OutputCollege {
    2. private List colleges;
    3. public OutputCollege(){
    4. colleges = new ArrayList();
    5. colleges.add(new ComputerCollege());
    6. colleges.add(new InfoManagerCollege());
    7. }
    8. // 打印学院以及下面的院系
    9. public void getCollegeAllDeparment(){
    10. Iterator iterator = colleges.iterator();
    11. while (iterator.hasNext()){
    12. //获取到学院
    13. College college = iterator.next();
    14. System.out.println("-----" + college.getCollegeName() + "-----");
    15. //获取学院的迭代器
    16. //计算机学院用的数组存储,信息管理用列表存储,通过迭代器可统一使用
    17. Iterator collegeIterator = college.getIterator();
    18. while (collegeIterator.hasNext()){
    19. //获取到院系
    20. Department department = (Department) collegeIterator.next();
    21. System.out.println(department.getName() + " : " + department.getDescription());
    22. }
    23. }
    24. }
    25. }

    测试

    1. public class Client {
    2. public static void main(String[] args) {
    3. OutputCollege outputCollege = new OutputCollege();
    4. outputCollege.getCollegeAllDeparment();
    5. }
    6. }

    结果

    -----计算机学院-----
    计科 : 计算机科学与技术
    软工 : 软件工程
    网工 : 网络工程
    大数据 : 大数据
    -----信息管理学院-----
    信管 : 信息管理
    新计 : 信息计算

    二、ArrayList集合中应用的迭代器模式

    ArrayList实现了List接口

    1. public class ArrayList extends AbstractList
    2. implements List, RandomAccess, Cloneable, java.io.Serializable

    List 充当了聚合接口,含有一个  iterator() 方法,返回一个迭代器对象

    1. public interface List extends Collection {
    2. Iterator iterator();
    3. }

    ArrayList 是实现聚合接口 List 的子类,实现了iterator() 

    Itr 作为 ArrayList 内部类,充当具体实现迭代器 Iterator 的类

    1. public Iterator iterator() {
    2. return new Itr();
    3. }
    4. private class Itr implements Iterator {
    5. int cursor; // index of next element to return
    6. int lastRet = -1; // index of last element returned; -1 if no such
    7. int expectedModCount = modCount;
    8. public boolean hasNext() {
    9. return cursor != size;
    10. }
    11. @SuppressWarnings("unchecked")
    12. public E next() {
    13. checkForComodification();
    14. int i = cursor;
    15. if (i >= size)
    16. throw new NoSuchElementException();
    17. Object[] elementData = ArrayList.this.elementData;
    18. if (i >= elementData.length)
    19. throw new ConcurrentModificationException();
    20. cursor = i + 1;
    21. return (E) elementData[lastRet = i];
    22. }
    23. public void remove() {
    24. if (lastRet < 0)
    25. throw new IllegalStateException();
    26. checkForComodification();
    27. try {
    28. ArrayList.this.remove(lastRet);
    29. cursor = lastRet;
    30. lastRet = -1;
    31. expectedModCount = modCount;
    32. } catch (IndexOutOfBoundsException ex) {
    33. throw new ConcurrentModificationException();
    34. }
    35. }
    36. @Override
    37. @SuppressWarnings("unchecked")
    38. public void forEachRemaining(Consumersuper E> consumer) {
    39. Objects.requireNonNull(consumer);
    40. final int size = ArrayList.this.size;
    41. int i = cursor;
    42. if (i >= size) {
    43. return;
    44. }
    45. final Object[] elementData = ArrayList.this.elementData;
    46. if (i >= elementData.length) {
    47. throw new ConcurrentModificationException();
    48. }
    49. while (i != size && modCount == expectedModCount) {
    50. consumer.accept((E) elementData[i++]);
    51. }
    52. // update once at end of iteration to reduce heap write traffic
    53. cursor = i;
    54. lastRet = i - 1;
    55. checkForComodification();
    56. }
    57. final void checkForComodification() {
    58. if (modCount != expectedModCount)
    59. throw new ConcurrentModificationException();
    60. }
    61. }

    具体关系为:

    迭代器模式解决了不同集合(ArrayList ,LinkedList)   统一遍历问题

    三、迭代器模式的注意事项和细节

    优点

    1)提供一个统一的方法遍历对象,客户不用再考虑聚合的类型,使用一种方法就可以遍历对象了。

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

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

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

    缺点

    每个聚合对象都要一个迭代器,会生成多个迭代器不好管理类

  • 相关阅读:
    关于富文本编辑器wangeditor在vue3中的使用
    Linux 基础复习
    SQL笔记——数据库恢复技术
    JAVA计算机毕业设计中文网络小说平台系统Mybatis+源码+数据库+lw文档+系统+调试部署
    视频讲解vue2基础之渲染v-if/v-show/v-for/v-html
    Linux目录结构和重要文件路径
    【PostgreSQL内核学习(十五)—— (ExecutorRun)】
    [从零学习汇编语言] - 内中断
    为什么MySQL默认的隔离级别是RR而大厂使用的是RC?
    网络之数据链路层(PPP协议)
  • 原文地址:https://blog.csdn.net/qq_51409098/article/details/126935566