第二十章行为性模式—迭代器模式

news/2024/11/26 12:04:21/

文章目录

  • 迭代器模式
    • 解决的问题
    • 结构
    • 实例
    • 存在的问题
    • 适用场景
  • JDK 源码 - Iterator

行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式:

  • 类行为模式:采用继承机制来在类间分派行为

  • 对象行为模式:采用组合或聚合在对象间分配行为

由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。

行为型模式分为:

  • 模板方法模式
  • 策略模式
  • 命令模式
  • 职责链模式
  • 状态模式
  • 观察者模式
  • 中介者模式
  • 迭代器模式
  • 访问者模式
  • 备忘录模式
  • 解释器模式

以上 11 种行为型模式,除了模板方法模式解释器模式是类行为型模式,其他的全部属于对象行为型模式。

迭代器模式

迭代器模式:提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象底层的表现形式(列表,栈,树)。

解决的问题

聚合对象就是一个容器,容器肯定能够遍历元素,容器的主要职责是高效存储元素,对于复杂的结构存在多种遍历的方法(比如树),如果将遍历的方法写入容器中,就模糊了容器的主要功能是高效存储元素,迭代器就是将遍历发方法从容器抽离出来,这样我们遍历容器时,就去与迭代器接口去交互,而不需要与容器交互,符合依赖倒转原则

结构

  • Aggregate,抽象聚合角色:定义存储、添加、删除聚合元素以及创建迭代器对象的接口。
  • ConcreteAggregate,具体聚合角色:实现抽象聚合类,返回一个具体迭代器的实例。
  • Iterator,抽象迭代器角色:定义访问和遍历聚合元素的接口,通常包含 hasNext()、next() 等方法。
  • Concretelterator,具体迭代器角色:实现抽象迭代器接口中所定义的方法,完成对聚合对象的遍历,记录遍历的当前位置。

实例

image-20230525114505262)

实体类

@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Student {private String name;private String number;
}

抽象迭代器元素

public interface StudentIterator {//判断是否还有元素boolean hasNext();//获取下一个元素Student next();
}

具体迭代器

public class StudentIteratorImpl implements  StudentIterator{private final List<Student> list;private int position=0;// 记录遍历时的位置public StudentIteratorImpl(List<Student> list) {this.list = list;}@Overridepublic boolean hasNext() {return position<list.size();}@Overridepublic Student next() {//从集合获取指定位置的元素return list.get(position++);}
}

抽象聚合角色

public interface StudentAggregate {//添加学生功能void addStudent(Student student);// 删除学生功能void removeStudent(Student stu);// 获取迭代器对象功能StudentIterator getStudentIterator();
}

具体聚合角色

public class StudentAggregateImpl implements  StudentAggregate{private List<Student> list = new ArrayList<>();@Overridepublic void addStudent(Student student) {list.add(student);}@Overridepublic void removeStudent(Student student) {list.remove(student);}@Override//获取迭代器对象public StudentIterator getStudentIterator() {return new StudentIteratorImpl(list);}
}

测试

public class Client {public static void main(String[] args) {//创建聚合对象StudentAggregateImpl aggregate = new StudentAggregateImpl();//添加元素aggregate.addStudent(new Student("张三", "001"));aggregate.addStudent(new Student("李四", "002"));aggregate.addStudent(new Student("王五", "003"));aggregate.addStudent(new Student("赵六", "004"));//遍历聚合对象//1获取迭代器对象StudentIterator iterator = aggregate.getStudentIterator();//2遍历while (iterator.hasNext()){//3获取元素Student student = iterator.next();System.out.println(student);}}
Student(name=张三, number=001)
Student(name=李四, number=002)
Student(name=王五, number=003)
Student(name=赵六, number=004)

存在的问题

优点:

  • 支持以不同的方式遍历一个聚合对象,在同一个聚合对象上可以定义多种遍历方式。在迭代器模式中只需要用一个不同的迭代器来替换原有迭代器即可改变遍历算法,我们也可以自己定义迭代器的子类以支持新的遍历方式。

  • 迭代器简化了聚合类。由于引入了迭代器,在原有的聚合对象中不需要再自行提供数据遍历等方法,这样可以简化聚合类的设计。

  • 在迭代器模式中,由于引入了抽象层,增加新的聚合类和迭代器类都很方便,无须修改原有代码,满足 “开闭原则” 的要求。

缺点:

  • 增加了类的个数,这在一定程度上增加了系统的复杂性

适用场景

  • 当需要为聚合对象提供多种遍历方式时。
  • 当需要为遍历不同的聚合结构提供一个统一的接口时。
  • 当访问一个聚合对象的内容而无须暴露其内部细节的表示时。

JDK 源码 - Iterator

迭代器模式在 Java 的很多集合类中被广泛应用,接下来看看 Java 源码中是如何使用迭代器模式的。

List<String> list = new ArrayList<>();
Iterator<String> iterator = list.iterator(); // list.iterator()方法返回的肯定是Iterator接口的子实现类对象
while (iterator.hasNext()) {System.out.println(iterator.next());
}

Java 中的单列集合都使用到了迭代器,以 ArrayList 举例说明:

  • List:抽象聚合类
  • ArrayList:具体的聚合类
  • Iterator:抽象迭代器
  • list.iterator():返回的是实现了 Iterator 接口的具体迭代器对象
public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable {public Iterator<E> iterator() {return new Itr();}private class Itr implements Iterator<E> {int cursor;       // 下一个要返回元素的索引int lastRet = -1; // 上一个返回元素的索引int expectedModCount = modCount;Itr() {}//判断是否还有元素public boolean hasNext() {return cursor != size;}//获取下一个元素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];}...
}

这部分代码还是比较简单,大致就是在 iterator 方法中返回了一个实例化的 Iterator 对象。Itr 是一个内部类,它实现了 Iterator 接口并重写了其中的抽象方法。

当我们在使用 Java 开发的时候,想使用迭代器模式的话,只要让我们自己定义的容器类实现java.util.Iterable并实现其中的 iterator() 方法使其返回一个 java.util.Iterator 的实现类就可以了。


http://www.ppmy.cn/news/123239.html

相关文章

git 环境配置 + gitee拉取代码

好嘛 配环境的时候 老是忘记这个命令行 干脆自己写一个记录一下 也不用搜了 1.先从git官网下载git 安装 2.然后从gitee拉取代码的时候提示 这是因为换了新电脑没有加入新的公钥啦 哎 所以老是记不住命令行 first &#xff1a; git config --global user.name “Your Name” …

网络安全工程师的入门学习路径,年薪30W不是梦!

最近看到网上有很多人在问诸如&#xff1a;“怎样成为网络信息安全工程师”等相关问题&#xff0c;这可能与近几年网络安全事件频发&#xff0c;国家对于互联网信息安全和互联网舆情的重视程度不断提升有关&#xff0c;网络信息安全工程师随之成为炙手可热的职业。 首先&#…

Python通过paramiko的SFTP put上传大批量数据时出现的bug及解决方案

文章目录 前言一、报错情况二、解决方案1.路径问题2.权限不对3.写法问题4.paramiko版本问题5.sftp.put()参数问题 总结 前言 在通过paramiko中的sftp上传大批量数据时&#xff0c;遇到了很奇怪的情况&#xff1a;写好的程序在正常运行3天后&#xff0c;接下来的几天每天上传几…

充电桩测试设备TK4800充电机(桩)现校仪检定装置

TK4800是一套专用于检定电动汽车非车载充电机现场校验仪和电动汽车交流充电桩现场校验仪的装置&#xff0c;针对新能源汽车充电动态特性进行设计&#xff0c;支持稳态电能计量&#xff08;针对恒定负载&#xff09;和动态电能计量&#xff08;针对波动性负载&#xff09;两种模…

独立、相关、正交

文章目录 【1. 独立】【2. 相关】【3.正交】【4. 相互关系】相关和独立相关和正交独立和正交独立、不相关和正交小结 【5. 参考文献】 【1. 独立】 独立&#xff1a;对于两个随机变量 y 1 y_1 y1​ 和 y 2 y_2 y2​&#xff0c;若 y 1 y_1 y1​ 的有关信息不给出 y 2 y_2 …

信号调制的工作原理

要理解如何进行无线数据传输&#xff0c;我们需要了解&#xff1a; 什么是频率&#xff1f; 信息/数据信号 时间表示 频率表示&#xff0c;为什么它很重要&#xff1f; 滤波器如何工作&#xff1f; FCC通信频段 调制和解调 这些主题可能您在大学专业课上学过&#xff0c…

深入探讨JMeter中不为人知的JSONPath用法

在jmeter使用过程中&#xff0c;我们经常会看到接口返回数据类型为application/json&#xff0c;也就时我们常说的json格式。 而在功能测试时&#xff0c;我们经常会要对它的结果进行断言&#xff0c;确认结果是否与预期一致&#xff0c;有时候还会想从结果中提取某个值&#…

vue-cli3.0创建项目IE兼容处理

一、白屏处理 IE白屏&#xff0c;基本是JS代码报错&#xff0c;包括app.js报错或者chunk包报错&#xff0c;需要分以下几个步骤解决&#xff1a; 1. 安装sockjs-client包&#xff0c;npm i sockjs-client -D。 2. 安装babel-polyfill包&#xff0c;npm i babel-polyfill -D&…