AI智能
改变未来

设计模式学习笔记(十六)迭代器模式及其在Java 容器中的应用

迭代器(Iterator)模式,也叫做游标(Cursor)模式。我们知道,在Java 容器中,为了提高容器遍历的方便性,把遍历逻辑从不同类型的集合类中抽取出来,避免向外部暴露集合容器的内部结构。

一、迭代器模式介绍

迭代器模式也就是提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。它是一种行为型模式,下面就来看看迭代器模式的结构:

1.1 迭代器模式的结构

迭代器模式的结构很简单,就是将聚合对象中的遍历行为分离,并抽象成迭代器类来实现:

  • Aggregate

    :抽象聚合接口,定义对聚合对象的一些操作和创建迭代器对象的接口

  • Iterator

    :抽象迭代器接口,定义访问和遍历聚合元素的接口

  • Aggregate1

    :具体聚合实现,实现抽象聚合接口,返回一个具体迭代器实例对象

  • Iterator1

    :具体迭代器实现,实现抽象迭代器接口中所定义的方法

1.2 迭代器模式的实现

根据上面的类图,可以实现如下代码:

/*** @description: 抽象聚合接口* @author: wjw* @date: 2022/4/6*/public interface Aggregate {/*** 增加对象* @param obj 对象*/void add(Object obj);/*** 移除对象* @param obj 对象*/void remove(Object obj);/*** 调用迭代器* @return 迭代器*/Iterator getIterator();}/*** @description: 具体迭代器类* @author: wjw* @date: 2022/4/6*/public class Aggregate1 implements Aggregate{private List<Object> list = new ArrayList<>();@Overridepublic void add(Object obj) {list.add(obj);}@Overridepublic void remove(Object obj) {list.remove(obj);}@Overridepublic Iterator getIterator() {return new Iterator1(list);}}/*** @description: 抽象迭代器* @author: wjw* @date: 2022/4/6*/public interface Iterator {/*** 调用第一个对象* @return 对象*/Object first();/*** 调用下一个对象* @return 对象*/Object next();/*** 迭代器中是否还有下一个对象* @return*/boolean hasNext();}/*** @description: 具体迭代器类* @author: wjw* @date: 2022/4/6*/public class Iterator1 implements Iterator{private List<Object> list = null;private int index = -1;public Iterator1(List<Object> list) {this.list = list;}@Overridepublic Object first() {index = 0;Object obj = list.get(index);return obj;}@Overridepublic Object next() {Object obj = null;if (this.hasNext()) {obj = list.get(++index);}return obj;}@Overridepublic boolean hasNext() {if (index < list.size() - 1) {return true;} else {return false;}}}/*** @description: 客户端类* @author: wjw* @date: 2022/4/6*/public class Client {public static void main(String[] args) {Aggregate1 aggregate1 = new Aggregate1();aggregate1.add("A");aggregate1.add("B");aggregate1.add("C");System.out.println("聚合对象有:");Iterator iterator = aggregate1.getIterator();while (iterator.hasNext()) {Object obj = iterator.next();System.out.println(obj.toString());}Object first = iterator.first();System.out.println("第一个聚合对象是:" + first.toString());}}

客户端测试场结果为:

聚合对象有:ABC第一个聚合对象是:A

二、迭代器模式的应用场景

2.1 Java 集合容器

Java 集合容器中的使用就是容器中的迭代器了,以

ArrayList

为例,

ArrayList

是继承

Collection

的:

我们发现

ArrayList

类里面实现迭代器接口的内部类:

其中

Itr

实现

Iterator

ListItr

继承

Itr

并实现

ListIterator

ListIterator

Iterator

功能的扩展。所以实际上

ArrayList

是抽象聚合和抽象迭代器两者的具体实现,可以画出大致结构图如下:

举个使用

ArrayList

的例子:

public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();list.add("A");list.add("B");list.add("C");Iterator<String> iterator = list.iterator();System.out.println("ArrayList中的聚合对象为:");while (iterator.hasNext()) {String next = iterator.next();System.out.println(next);}}

输出结果:

ArrayList中的聚合对象为:ABC

在日常业务的开发中,迭代器模式使用的场景并不多,下面就来看看关于迭代器的实战

三、迭代器模式实战

在本案例中模拟迭代遍历输出公司中树形结构的组织结构关系中雇员列表:

利用迭代器模式实现的结构如下:

上面结构是以Java容器中迭代器模式基础构建的,左边是迭代器的定义,右边是实现的迭代器功能。具体代码结构图如下:

├─src│  ├─main│  │  ├─java│  │  │  ├─group│  │  │  │      Employee.java│  │  │  │      GroupStructure.java│  │  │  │      Link.java│  │  │  ││  │  │  └─lang│  │  │          Collection.java│  │  │          Iterable.java│  │  │          Iterator.java│  │  ││  │  └─resources│  └─test│      └─java│              ApiTest.java

对于

lang

包下是迭代器实现部分,具体代码如下:

/*** @description: 可迭代接口定义* @author: wjw* @date: 2022/4/6*/public interface Iterator<E> {boolean hasNext();E next();}/*** @description:* @author: wjw* @date: 2022/4/6*/public interface Iterable<E> {Iterator<E> iterator();}/*** @description: 集合功能接口* @author: wjw* @date: 2022/4/6*/public interface Collection<E, L> extends Iterable<E> {boolean add(E e);boolean remove(E e);boolean addLink(String key, L l);boolean removeLink(String key);/*** 继承Iterable接口的方法* @return Iterator*/@OverrideIterator<E> iterator();}

group

包下是组织结构以及聚类对象及其实现,具体代码如下所示:

/*** @description: 雇员类* @author: wjw* @date: 2022/4/6*/public class Employee {private String uId;private String name;private String desc;public Employee(String uId, String name, String desc) {this.uId = uId;this.name = name;this.desc = desc;}public String getuId() {return uId;}public void setuId(String uId) {this.uId = uId;}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;}}/*** @description: 树节点链路* @author: wjw* @date: 2022/4/6*/public class Link {private String fromId;private String toId;public Link(String fromId, String toId) {this.fromId = fromId;this.toId = toId;}public String getFromId() {return fromId;}public void setFromId(String fromId) {this.fromId = fromId;}public String getToId() {return toId;}public void setToId(String toId) {this.toId = toId;}}/*** @description: 迭代器功能实现* @author: wjw* @date: 2022/4/6*/public class GroupStructure implements Collection<Employee, Link> {/**组织ID*/private String groupId;/**组织名称*/private String groupName;/**雇员列表*/private Map<String, Employee> employeeMap = new ConcurrentHashMap<>();/**组织架构关系*/private Map<String, List<Link>> linkMap = new ConcurrentHashMap<>();/**反向关系链*/private Map<String, String> invertedMap = new ConcurrentHashMap<>();public GroupStructure(String groupId, String groupName) {this.groupId = groupId;this.groupName = groupName;}@Overridepublic boolean add(Employee employee) {return null != employeeMap.put(employee.getuId(), employee);}@Overridepublic boolean remove(Employee employee) {return null != employeeMap.remove(employee.getuId());}@Overridepublic boolean addLink(String key, Link link) {invertedMap.put(link.getToId(), link.getFromId());if (linkMap.containsKey(key)) {return linkMap.get(key).add(link);} else {List<Link> links = new LinkedList<>();links.add(link);linkMap.put(key, links);return true;}}@Overridepublic boolean removeLink(String key) {return null != linkMap.remove(key);}@Overridepublic Iterator<Employee> iterator() {return new Iterator<Employee>() {HashMap<String, Integer> keyMap = new HashMap<>();int totalIdx = 0;//雇员ID,Fromprivate String fromId = groupId;//雇员ID,Toprivate String toId = groupId;@Overridepublic boolean hasNext() {return totalIdx < employeeMap.size();}@Overridepublic Employee next() {List<Link> links = linkMap.get(toId);int cursorIdx = getCursorIdx(toId);//同级扫描if (null == links) {cursorIdx = getCursorIdx(fromId);links = linkMap.get(fromId);}//上级节点扫描while (cursorIdx > links.size() - 1) {fromId = invertedMap.get(fromId);cursorIdx = getCursorIdx(fromId);links = linkMap.get(fromId);}//获取节点Link link = links.get(cursorIdx);toId = link.getToId();fromId = link.getFromId();totalIdx++;//返回最终结果return employeeMap.get(link.getToId());}//给每个层级定义宽度遍历进度public int getCursorIdx(String key) {int idx = 0;if (keyMap.containsKey(key)) {idx = keyMap.get(key);keyMap.put(key, ++idx);} else {keyMap.put(key, idx);}return idx;}};}}

最后是测试类及其结果:

/*** @description: 单元测试类* @author: wjw* @date: 2022/4/6*/public class ApiTest {private Logger logger = LoggerFactory.getLogger(ApiTest.class);@Testpublic void test_iterator() {GroupStructure groupStructure = new GroupStructure("1", "ethan");groupStructure.add(new Employee("2", "花花", "二级部门"));groupStructure.add(new Employee("3", "豆包", "二级部门"));groupStructure.add(new Employee("4", "蹦蹦", "三级部门"));groupStructure.add(new Employee("5", "大烧", "三级部门"));groupStructure.add(new Employee("6", "虎哥", "四级部门"));groupStructure.add(new Employee("7", "玲姐", "四级部门"));groupStructure.add(new Employee("8", "秋雅", "四级部门"));//添加节点链接groupStructure.addLink("1", new Link("1", "2"));groupStructure.addLink("1", new Link("1", "3"));groupStructure.addLink("2", new Link("2", "4"));groupStructure.addLink("2", new Link("2", "5"));groupStructure.addLink("5", new Link("5", "6"));groupStructure.addLink("5", new Link("5", "7"));groupStructure.addLink("5", new Link("5", "8"));Iterator<Employee> iterator = groupStructure.iterator();while (iterator.hasNext()) {Employee employee = iterator.next();logger.info("{},雇员 Id: {} Name: {}", employee.getDesc(), employee.getuId(), employee.getName());}}}
21:50:11.087 [main] INFO  ApiTest - 二级部门,雇员 Id: 2 Name: 花花21:50:11.089 [main] INFO  ApiTest - 三级部门,雇员 Id: 4 Name: 蹦蹦21:50:11.089 [main] INFO  ApiTest - 三级部门,雇员 Id: 5 Name: 大烧21:50:11.089 [main] INFO  ApiTest - 四级部门,雇员 Id: 6 Name: 虎哥21:50:11.089 [main] INFO  ApiTest - 四级部门,雇员 Id: 7 Name: 玲姐21:50:11.089 [main] INFO  ApiTest - 四级部门,雇员 Id: 8 Name: 秋雅21:50:11.089 [main] INFO  ApiTest - 二级部门,雇员 Id: 3 Name: 豆包

参考资料

《重学Java设计模式》

http://c.biancheng.net/view/1395.html

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » 设计模式学习笔记(十六)迭代器模式及其在Java 容器中的应用