一、迭代器模式介绍
1. 解决的问题
次要解决遍历整个汇合对象的问题。
2. 定义
迭代器模式 是一种行为设计模式,能在不裸露底层表现形式(列表、栈和树等)的状况下遍历汇合中所有的元素。
3. 利用场景
- 当汇合背地为简单的数据结构,且心愿对客户端暗藏其复杂性时(处于应用便利性或安全性思考),能够应用迭代器模式。
- 缩小程序中反复的遍历代码,能够应用迭代器模式。
- 心愿代码可能遍历不同的甚至无奈预知的数据结构,能够应用迭代器模式。
二、迭代器模式优缺点
1. 长处
- 繁多职责准则:通过将体积宏大的遍历算法代码抽取为独立的类,能够对客户端代码和汇合进行整顿。
- 开闭准则:可实现新型的汇合和迭代器并将其传递给现有代码,无需批改现有代码。
- 能够并行遍历同一汇合,因为每个迭代器对象都蕴含其本身的遍历状态;同时,也能够暂停遍历并在须要时持续。
2. 毛病
- 如果程序只与简略的汇合进行交互,应用迭代器模式可能会矫枉过正。
- 对于某些非凡汇合,应用迭代器可能比间接遍历的效率低。
三、迭代器模式利用实例:你有多少 QQ 好友呢?
1. 实例场景
微信的崛起,就是 QQ 的落寞,当初用 QQ 的应该越来越少了,但 QQ 很多性能还是挺好用的,比方好友的分组性能,这样就齐全能够将从学校、网络上、工作等意识的好友离开,那么离开当前,怎么晓得到底有多少 QQ 好友呢?
明天,以遍历各个分组的好友为例,介绍一下迭代器模式。
2. 迭代器模式实现
2.1 工程构造
iterator-pattern
└─ src
├─ main
│ └─ java
│ └─ org.design.pattern.iterator
│ ├─ model
│ │ ├─ Friend.java
│ │ └─ Group.java
│ └─ tool
│ ├─ Iterator.java
│ ├─ Collection.java
│ └─ impl
│ ├─ IteratorImpl.java
│ └─ CollectionImpl.java
└─ test
└─ java
└─ org.design.pattern.iterator
└─ IteratorTest.java
2.2 代码实现
2.2.1 实体类
QQ 好友
/**
* QQ 好友
*/
@Getter
@Setter
@AllArgsConstructor
public class Friend {
/**
* 用户 id
*/
private String id;
/**
* 昵称
*/
private String nickname;
/**
* 备注
*/
private String noteName;
}
QQ 分组
/**
* QQ 分组
*/
@Setter
@Getter
@AllArgsConstructor
public class Group {
/**
* 分组 id
*/
private String id;
/**
* 分组名称
*/
private String name;
/**
* 好友列表
*/
private CollectionImpl<Friend> friendList;
/**
* 增加好友
*
* @param friend 好友
* @return boolean
*/
public boolean addFriend(Friend friend) {return friendList.add(friend);
}
/**
* 删除好友
*
* @param friend 好友
* @return boolean
*/
public boolean removeFriend(Friend friend) {return friendList.remove(friend);
}
}
2.2.2 工具类
迭代器接口
/**
* 迭代器接口
*
* @param <T>
*/
public interface Iterator<T> {
/**
* 是否有下一个节点
*
* @return boolean
*/
boolean hasNext();
/**
* 获取下一个节点
*
* @return T
*/
T getNext();}
汇合接口
/**
* 汇合接口
* @param <E>
*/
public interface Collection<E> {
/**
* 创立迭代器
*
* @return Iterator<E>
*/
Iterator<E> createIterator();
/**
* 增加汇合元素
*
* @param e 汇合元素
* @return boolean
*/
boolean add(E e);
/**
* 删除汇合元素
*
* @param e 汇合元素
* @return boolean
*/
boolean remove(E e);
/**
* 获取汇合长度
*
* @return Integer
*/
Integer size();
/**
* 获取汇合元素
*
* @param index 索引
* @return E
*/
E get(Integer index);
}
迭代器实现类
/**
* 迭代器实现类
*
* @param <E>
*/
public class IteratorImpl<E> implements Iterator<E> {
private final CollectionImpl<E> groupCollection;
private int currentIndex;
public IteratorImpl(CollectionImpl<E> groupCollection) {
this.currentIndex = 0;
this.groupCollection = groupCollection;
}
/**
* 是否有下一个节点
*
* @return boolean
*/
@Override
public boolean hasNext() {return currentIndex < groupCollection.size();
}
/**
* 获取下一个节点
*
* @return E
*/
@Override
public E getNext() {if (!hasNext()) {return null;}
E e = groupCollection.get(currentIndex);
currentIndex++;
return e;
}
}
汇合实现类
/**
* 汇合实现类
*
* @param <E>
*/
public class CollectionImpl<E> implements Collection<E> {
private final List<E> groupList;
public CollectionImpl() {this.groupList = new ArrayList<>();
}
/**
* 创立迭代器
*
* @return Iterator<E>
*/
@Override
public Iterator<E> createIterator() {return new IteratorImpl<E>(this);
}
/**
* 增加汇合元素
*
* @param e 汇合元素
* @return boolean
*/
@Override
public boolean add(E e) {return groupList.add(e);
}
/**
* 删除汇合元素
*
* @param e 汇合元素
* @return boolean
*/
@Override
public boolean remove(E e) {return groupList.remove(e);
}
/**
* 获取汇合长度
*
* @return Integer
*/
@Override
public Integer size() {return groupList.size();
}
/**
* 获取汇合元素
*
* @param index 索引
* @return E
*/
@Override
public E get(Integer index) {return groupList.get(index);
}
}
2.3 测试验证
2.3.1 测试验证类
/**
* 迭代器测试
*/
public class IteratorTest {
@Test
public void testIterator() {CollectionImpl<Friend> friendCollectionOne = new CollectionImpl<>();
friendCollectionOne.add(new Friend("1", "小可乐", "王明"));
friendCollectionOne.add(new Friend("2", "阿毛明天睡醒了", "三毛"));
friendCollectionOne.add(new Friend("3", "楚语吴歌", "夏亚"));
CollectionImpl<Friend> friendCollectionTwo = new CollectionImpl<>();
friendCollectionTwo.add(new Friend("1", "系鞋带深造员", "张涛"));
CollectionImpl<Friend> friendCollectionThree = new CollectionImpl<>();
friendCollectionThree.add(new Friend("1", "饕餮少女", "王霖"));
CollectionImpl<Group> groupCollection = new CollectionImpl<>();
groupCollection.add(new Group("1", "同学", friendCollectionOne));
groupCollection.add(new Group("2", "网友", friendCollectionTwo));
groupCollection.add(new Group("3", "共事", friendCollectionThree));
Iterator<Group> groupIterator = groupCollection.createIterator();
while (groupIterator.hasNext()) {Group group = groupIterator.getNext();
System.out.printf("group id is %s, group name is %s", group.getId(), group.getName());
System.out.println();
Iterator<Friend> friendIterator = group.getFriendList().createIterator();
while (friendIterator.hasNext()) {Friend friend = friendIterator.getNext();
System.out.printf(
"Friend nickname is %s, Friend noteName is %s",
friend.getNickname(),
friend.getNoteName());
System.out.println();}
System.out.println();}
}
}
2.3.2 测试后果
group id is 1, group name is 同学
Friend nickname is 小可乐, Friend noteName is 王明
Friend nickname is 阿毛明天睡醒了, Friend noteName is 三毛
Friend nickname is 楚语吴歌, Friend noteName is 夏亚
group id is 2, group name is 网友
Friend nickname is 系鞋带深造员 , Friend noteName is 张涛
group id is 3, group name is 共事
Friend nickname is 饕餮少女 , Friend noteName is 王霖
Process finished with exit code 0
四、迭代器模式构造
- 迭代器(Iterator)接口申明了遍历汇合所需的操作:获取下一个元素、获取以后地位和从新开始迭代等。
- 具体迭代器(Concrete Iterators)实现遍历汇合的一种特定算法。迭代器对象必须追踪本身的遍历进度。这使得多个迭代器能够互相独立地遍历同一汇合。
-
汇合(Collection)接口申明一个或多个办法来获取与汇合兼容的迭代器。
留神:返回办法的类型必须被申明为迭代器接口,从而使具体汇合能够返回各种不同品种的迭代器。
- 具体汇合(Concrete Collections)会在客户端申请迭代器时返回一个特定的具体迭代器实体。
-
客户端(Client)通过汇合和迭代器的接口与两者进行交互。这样一来客户端无需与具体类耦合,容许同一客户端代码应用各种不同的汇合和迭代器
客户端通常不会自行创立迭代器,而是会从汇合中获取。但在特定状况下,客户端能够间接创立一个迭代器。
设计模式并不难学,其自身就是多年教训提炼出的开发指导思想,关键在于多加练习,带着应用设计模式的思维去优化代码,就能构建出更正当的代码。
源码地址:https://github.com/yiyufxst/design-pattern-java
参考资料:
小博哥重学设计模式:https://github.com/fuzhengwei/itstack-demo-design
深刻设计模式:https://refactoringguru.cn/design-patterns/catalog