设计模式之迭代器模式
迭代器模式
定义:提供一种方法,顺序访问一个集合对象中的各个元素,而又不暴露该对象的内部表示
类型:行为型
适用场景:
- 访问一个集合对象的内容而无需暴露它的内部表示
- 为遍历不同的集合结构提供一个统一的接口
优点:
- 分离了集合对象的遍历行为
- 封装性良好,用户只需要得到迭代器就可以遍历,而对于遍历算法则不用去关心
缺点:
- 类的个数成对增加
UML类图:
抽象容器角色(Aggregate):负责提供创建具体迭代器角色的接口,一般是一个接口,提供一个iterator()方法,例如java中的Collection接口,List接口,Set接口等。
具体容器角色(ConcreteAggregate):就是实现抽象容器的具体实现类,比如List接口的有序列表实现ArrayList,List接口的链表实现LinkedList,Set接口的哈希列表的实现HashSet等。
抽象迭代器角色(Iterator):负责定义访问和遍历元素的接口。
具体迭代器角色(ConcreteIterator):实现迭代器接口,并要记录遍历中的当前位置。
示例
举一个简单的例子,有一个书柜,书柜上放有一堆的书籍,我们在可以对这个书柜存放书籍或移除书籍,也可以查看所有书籍的信息,这里的目的是遍历获取到所有的书籍信息
- 书籍类
/**
* 书籍
*/
public class Book {
/**
* 书籍名称
*/
private String name;
/**
* 书籍价格
*/
private double price;
public Book(String name, double price) {
this.name = name;
this.price = price;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
}
- 书籍集合接口
/**
* 书籍集合接口
*/
public interface BookAggregate {
/**
* 添加书籍
* @param book
*/
void addCourse(Book book);
/**
* 移除书籍
* @param book
*/
void removeCourse(Book book);
/**
* 获取书籍迭代器
* @return
*/
Iterator getBookIterator();
}
- 书籍集合实现类
/**
* 书籍集合实现类
*/
public class BookAggregateImpl implements BookAggregate{
private List<Book> bookList = new ArrayList<>();
@Override
public void addCourse(Book book) {
bookList.add(book);
}
@Override
public void removeCourse(Book book) {
bookList.remove(book);
}
@Override
public Iterator getBookIterator() {
return new BookIterator(bookList);
}
}
- 迭代器接口
/**
* 迭代器接口
*/
public interface Iterator {
/**
* 获取下一个书籍元素
* @return
*/
Book nextBook();
/**
* 是否是最后一个
* @return
*/
boolean isLast();
}
- 具体书籍迭代器
package com.yaolong.demo.designpattern.behaviour.iterator;
import java.util.List;
/**
* 具体书籍迭代器
*/
public class BookIterator implements Iterator {
private List<Book> bookList;
private int position;
private Book book;
public BookIterator(List bookList) {
this.bookList = bookList;
}
@Override
public Book nextBook() {
System.out.println("返回书籍,位置是" + position);
book = bookList.get(position);
position++ ;
return book;
}
@Override
public boolean isLast() {
if(position < bookList.size()){
return false;
}
return true;
}
}
- 客户端
/**
* 迭代器模式
*/
public class Client {
public static void main(String[] args) {
Book book1 = new Book("辟邪剑谱", 20);
Book book2 = new Book("葵花宝典", 32);
Book book3 = new Book("九阳神功", 40);
Book book4 = new Book("九阴真经", 50);
BookAggregate bookAggregate = new BookAggregateImpl();
bookAggregate.addCourse(book1);
bookAggregate.addCourse(book2);
bookAggregate.addCourse(book3);
bookAggregate.addCourse(book4);
Iterator bookIterator = bookAggregate.getBookIterator();
while(!bookIterator.isLast()){
System.out.println(bookIterator.nextBook());
}
//移除后
System.out.println("");
System.out.println("移除一本书后:");
bookIterator = bookAggregate.getBookIterator();
bookAggregate.removeCourse(book1);
while(!bookIterator.isLast()){
System.out.println(bookIterator.nextBook());
}
}
}
返回书籍,位置是0
Book{name='辟邪剑谱', price=20.0}
返回书籍,位置是1
Book{name='葵花宝典', price=32.0}
返回书籍,位置是2
Book{name='九阳神功', price=40.0}
返回书籍,位置是3
Book{name='九阴真经', price=50.0}移除一本书后:
返回书籍,位置是0
Book{name='葵花宝典', price=32.0}
返回书籍,位置是1
Book{name='九阳神功', price=40.0}
返回书籍,位置是2
Book{name='九阴真经', price=50.0}
以上的例子就是我们自定义了一个迭代器接口并实现了迭代器的功能,BookAggregate实例将集合的位置判断、遍历行为委托给了Iterator实例,而不需要向客户端暴露自己内部的集合结构。通常为了方便维护,这个迭代器实现我们以一个内部类的进行提供。实际上,我们一般很少自己去定义迭代器接口,如jdk中提供了java.lang.Iterable(相当于BookAggregate)和java.util.Iterator(相当于我们上面定义的Iterator)都是现成的接口,如果我们自己定义的数据结构需要实现遍历输出,实现这两个接口即可
相关的设计模式
- 迭代器模式和访问者模式
都是迭代地访问集合中的各个元素,访问者模式中扩展开放的部分是作用于对象的操作上,而在迭代器模式中,扩展开放的部分是在集合对象的种类上,二者的实现方式上有很大的区别
使用典范
- java.util.ArrayList
参考
原文地址:https://www.cnblogs.com/DiDi516/p/12733131.html
- Flash/Flex学习笔记(27):摄像头/麦克风的视频/音量指示器
- Flash/Flex学习笔记(26):AS3自定义右键菜单
- Python27中Json对中文的处理
- Python在VSCode中进入交互界面调试
- CentOS7下单机部署RabbltMQ环境的操作记录
- Flash/Flex学习笔记(24):粒子效果
- 针对业务日志的监控报警设置
- 对广晟有色的数据分析
- Flash/Flex学习笔记(22):滤镜学习
- Python输出信息
- Flash/Flex学习笔记(21):利用colorTransform改变对象的颜色及透明度
- 网站访问状态和超时时间监控报警设置
- 为treeview添加客户端事件
- Flash/Flex学习笔记(20):贝塞尔曲线
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- vue 随记(3):“新时代”的姿势
- 归并排序 O(nLogn)
- 读书笔记--Android系统启动
- Swift 数组(Arrays)
- Swift 多行字符串字面量
- 服务器配置ssh密钥登陆
- Swift 区间运算符
- Spring Security 实战干货:理解AuthenticationManager
- 深度学习|Tensorflow2.0基础
- 【Rust日报】2020-07-20 boids算法, tide, popol, Calcite
- Cell Ontology:解析细胞类型新维度
- 软件设计思想:池化技术
- MySQL变量声明、赋值和使用
- Google Analytics和Adobe Analytics中的数据层dataLayer
- java多线程关键字volatile、lock、synchronized