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

news2024/9/22 19:22:03

文章目录

  • 迭代器模式
    • 解决的问题
    • 结构
    • 实例
    • 存在的问题
    • 适用场景
  • 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;
    }

    @Override
    public boolean hasNext() {
        return position<list.size();
    }

    @Override
    public 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<>();
    @Override
    public void addStudent(Student student) {
        list.add(student);
    }

    @Override
    public 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.coloradmin.cn/o/593968.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

“30分钟”带你走进线性回归的世界,轻松学习互联网营销推荐算法!

前言 本章主要介绍用于推荐系统的算法-线性回归算法的推导介绍&#xff0c;文章思路如下&#xff1a;由机器学习介绍&#xff0c;到监督学习&#xff0c;并重点介绍监督学习中回归问题里面的线性回归问题及推导。 可能需要大家具备一定的统计学、高数相关知识。 一、由机器学…

k8s入门(一)之pod创建、label使用、污点、亲和性、RS

一、创建一个pod [rootmaster01 ~]# kubectl create ns prod [rootmaster01 ~]# cat pod.yaml apiVersion: v1 kind: Pod metadata:name: pod-demonamespace: prodlabels:app: myapp spec:containers:- name: test1image: busybox:latestcommand:- "/bin/sh"- "…

问题记录 bug1-系统上电挂载异常分区,df与du命令查看文件使用大小显示不一样

linux磁盘分区 在Linux中&#xff0c;一切皆目录&#xff0c;每一块硬盘分区对应Linux的一个目录&#xff0c;所以我们可以通过管理目录来管理硬盘分区&#xff0c;而将硬盘分区与文件目录关联的操作就称为“挂载”【mount】&#xff0c;反之为“卸载”【unmount】 emmc&…

C高级 text

1.从命令行传参传入两个整数&#xff0c;整数1代表从整数几开始求和&#xff0c;整数2代表求和到整数几为止 2.打印99乘法表 3.输入年月日&#xff0c;计算是该年的第几天 1. 2. 3.

Linux进程基础

进程指正在运行的程序&#xff0c;如下图示&#xff0c;是资源分配的最小单位&#xff0c;可以通过“ps ”或“top”等命令查看正 在运行的进程&#xff0c;线程是系统的最小调度单位&#xff0c;一个进程可以拥有多个线程&#xff0c;同一进程里的线程可以共享此 进程的同一资…

Server版支持即将到期,Jira和Confluence如何迁移?(2)

到2024年2月&#xff0c;Atlassian将终止对Server产品及插件的所有支持。是时候制定您的迁移计划了——Atlassian为您提供两种迁移选择&#xff0c;一是本地部署的数据中心版本&#xff0c;中国用户25人以上即可使用&#xff0c;二是云版。作为Atlassian全球白金合作伙伴&#…

Markdown可以在线编辑吗?这个办法很好用

Markdown是一种轻量级标记语言&#xff0c;它使用简单的语法来创建文本&#xff0c;非常易于学习。它最初被设计为一种用于写作的格式&#xff0c;但现在已经成为了一种非常受欢迎的文本编辑工具。 作为一个较为方便的在线文本编辑器&#xff0c;它可以用代码代替文字&#xf…

一篇完整的测试方案怎么写

看上面的目录&#xff0c;详细 文档说明 文档名称 创建人/修改人 版本 时间 备注 v1.0 2022-11-17 新建 v1.1 2022-11-25 v1.2 2022-12-05 v2.0 2022-12-13 v2.1 2022-12-14 一、文档目的 为软件开发项目管理者、软件工程师、系统维护工程师、测试…

如何开发合成物品功能?

UE5 插件开发指南 前言0 数据结构1 合成面板UI组件2 小结前言 现在策划有一个合成物品的需求:可以将多个低级物品合成高级物品,如果背包中已有低级物品了,合成时需要减掉物品的费用,只需要支付合成费;提供玩家一个合成物品的层级视图,以便于玩家有节奏的购买物品,如下图…

电影《刀剑神域进击篇:暮色黄昏》观后感

上周看了电影《刀剑神域进击篇&#xff1a;暮色黄昏》&#xff0c;刀剑神域系列质量还是非常不错的&#xff0c; 本部电影讲述主角团队攻克boss&#xff0c;阻止公会团体互相打架的故事。 刀剑系列&#xff0c;记得当初是以一部连载动漫为开端&#xff0c;如果不是特别喜欢看动…

计算机网络—HTTP基本概念、HTTPS、HTTP状态码、HTTP缓存、HTTP请求

参考小林coding HTTP基本概念 HTTP是超文本传输协议。所谓的超文本&#xff0c;就是超越了普通文本的文本&#xff0c;最关键的是有超链接&#xff0c;能从一个超文本跳转到另一个超文本。 HTML是最常见的超文本&#xff0c;本身是纯文字文件&#xff0c;但是内部使用很多标签…

Scrum敏捷项目管理实例

这是一个Scrum敏捷单团队敏捷开发示例。 1、建立产品路线图 首先我们需要为这个项目创建一个产品路线图&#xff0c;产品路线图是一个高层次的战略计划&#xff0c;它描述了产品在未来一段时间可能会如何发展和壮大&#xff0c;产品路线图确保整个产品团队持续关注产品的目标…

GEE:对Landsat遥感影像进行处理,水体提取与可视化

作者:CSDN @ _养乐多_ 本文介绍了通过Google Earth Engine平台,并使用Landsat卫星遥感数据提取水体掩膜的方法和代码。通过裁剪和去除云等处理步骤,最终得到具有水体掩膜的影像,并进行可视化和导出。这种方法基于归一化水体指数(MNDWI)和OTSU阈值计算技术,使用了一个自…

MyBatis(MyBatis环境搭建,单表操作)

目录 MyBatis 环境搭建 1.添加 Mybatis 框架支持 2.设置 MyBatis 配置信息 2.1.设置数据库连接的相关信息 2.2 Mybatis xml 保存路径和 xml命名格式 ​编辑 MyBatis 模式开发 Mybatis xml 模板 查询表内容 单元测试 以根据id,查询用户对象这个方法为例 获取动态参数的…

警惕,最近的副业兼职诈骗。

大家好&#xff0c;我是鸟哥。 今天和大家聊聊最近超级猖狂的几类诈骗。 一、副业诈骗。最近两年“副业刚需”这个口号很流行&#xff0c;尤其是今年&#xff0c;职场动荡、工作难找&#xff0c;副业刚需变成了副业焦虑&#xff0c;骗子们也正是抓住了大家的这个心理&#xf…

【Vue全家桶实现电商系统】— VSCode配置Git(二)

【Vue全家桶实现电商系统】— VSCode配置Git&#xff08;二&#xff09; 当我们在VScode中编写代码后&#xff0c;需要提交到git仓库时&#xff0c;但是我们又不想切换到git的命令行窗口&#xff0c;我们可以在 VScode中配置git&#xff0c;然后就可以很方便快捷的把代码提交…

JavaScript中的Hook技术:特性、优点、缺点和使用场景

引言&#xff1a; 随着JavaScript的不断发展&#xff0c;开发者们正在寻找更灵活和可扩展的方式来修改或扩展现有的代码。其中一种广泛应用的技术是"Hook"&#xff0c;它允许开发者拦截和修改现有的函数或方法的行为。本文将详细介绍JavaScript中的Hook技术&#xf…

软件确认测试、验收测试和系统测试有什么区别和联系?

软件确认测试、验收测试和系统测试都是软件测试过程中的重要环节&#xff0c;它们各自有不同的测试侧重点和目标&#xff0c;但也有一些联系。 1、软件确认测试 称为单元测试或白盒测试&#xff0c;是对软件中各个模块的基本功能进行测试的一种测试方式&#xff0c;主要使用…

【Python从入门到进阶】22、urllib库基本使用

接上篇《21、爬虫相关概念介绍》 上一篇我们介绍了爬虫的相关概念&#xff0c;本篇我们来介绍一下用Python实现爬虫的必备基础&#xff0c;urllib库的学习。 一、Python库的概念 我们今后的学习可能需要用到很多python库&#xff08;library&#xff09;&#xff0c;及引用其…

在阿里外包干了3个月,我果断跑路了

有一种打工人的羡慕&#xff0c;叫做“大厂”。 真是年少不知大厂香&#xff0c;错把青春插稻秧。 但是&#xff0c;在深圳有一群比大厂员工更庞大的群体&#xff0c;他们顶着大厂的“名”&#xff0c;做着大厂的工作&#xff0c;还可以享受大厂的伙食&#xff0c;却没有大厂…