2021年11月27日18:24:29
迭代器模式
定義
Provide a way to access the elements of an aggregate object sequentially without
exposing its underlying representation. ——《Design Patterns: Elements of Reusable Object-Oriented Software》
提供一種順序訪問集合的元素而不暴露其底層表示的方法。 ——《設計模式:可復用面向對象軟件的基礎》
迭代器模式是一種行為型模式。
明明講
迭代器模式就是提供一種遍歷的方法,這種方法有兩個特點:一是按你想要的方式訪問到你想訪問的元素,二是不暴露底層是什么存的,怎么存的。
在開發過程中,我們使用類庫提供給我們的集合,遍歷集合中的元素,使用的就是迭代器。一般情況下,單單作為使用者,我們是不會去關注這些集合底層結構是什么,只需要拿到我們需要的數據,進行業務邏輯的處理就可以了。但是呢,作為一個優秀的開發者,當然要深入了解各種集合的數據結構及操作的。當然啦,我們是不會說我們是為了面試才去了解的啦。(此處應該有表情)
常見用法:
List<String> list = new ArrayList<>();
list.add("ming");
list.add("ming");
list.add("come");
for(String s : list) {
System.out.println(s);
}
上面代碼中的for循環遍歷列表中的數據,Java編譯器會將這段代碼變成使用ArrayList中的迭代器去遍歷數據。編譯之后再反編譯,代碼如下:
List<String> list = new ArrayList();
list.add("ming");
list.add("ming");
list.add("come");
Iterator var1 = list.iterator();
while(var1.hasNext()) {
String s = (String)var1.next();
System.out.println(s);
}
圖示
迭代器模式結構圖:
角色
抽象迭代器角色(Iterator):
- 定義一個接口,用於訪問和遍歷元素,它的方法一般有:first、next、hasNext等。
具體迭代器角色(ConcreteIterator):
- 實現【抽象迭代器角色】定義的執行操作
- 記錄集合迭代時的當前位置,如圖中的currentItem()方法
- 當客戶端控制迭代,迭代器被稱作外部迭代器;當迭代器控制迭代,迭代器是內部迭代器。(When the client controls the iteration, the iterator is called an external
iterator, and when the iterator controls it, the iterator is aninternal iterator.) - Java類庫中AbstractList、ArrayList、HashMap中都有具體迭代器
抽象集合角色(Aggregate):
- 定義了一個接口,用於創建迭代器對象
具體集合角色(ConcreteAggregate):
- 實現【抽象集合角色】,實現創建迭代器對象方法,返回一個迭代器實例
代碼示例
家有小女,名為曉月,一歲有余,嚶嚶學語。
除夕佳節,給家人拜年,爺爺奶奶,爸爸媽媽,叔叔嬸嬸,還有曉月自己,新年快樂。
類圖:
抽象迭代器角色:
public interface NameIterator {
String next();
boolean hastNext();
}
抽象集合角色:
public interface FamilyAggregate {
NameIterator createIterator();
boolean addFamily(int generation, String name);
}
具體集合角色和具體迭代器角色:
// 具體集合類
public class FamilyAggregateImpl implements FamilyAggregate {
private int generation;
private List<String>[] generations;
public FamilyAggregateImpl(int generation) {
this.generation = generation;
this.generations = initFamily(generation);
}
private List<String>[] initFamily(int generation) {
List<String>[] name = new ArrayList[generation];
for (int i = 0; i < generation; i++) {
name[i] = new ArrayList<>();
}
return name;
}
public boolean addFamily(int generation, String name) {
return generations[generation - 1].add(name);
}
@Override
public NameIterator createIterator() {
return new NameIteratorImpl();
}
// 具體迭代器
private class NameIteratorImpl implements NameIterator {
int currentGeneration;
int cursor;
NameIteratorImpl() {
this.currentGeneration = FamilyAggregateImpl.this.generation;
}
@Override
public String next() {
int i = cursor;
List<String>[] generations = FamilyAggregateImpl.this.generations;
if (currentGeneration == 1 && cursor == generations.length) {
System.out.println("無剩余可遍歷");
}
String name = generations[currentGeneration - 1].get(i);
cursor = i + 1;
if (cursor == generations[currentGeneration - 1].size()) {
currentGeneration--;
cursor = 0;
}
return name;
}
@Override
public boolean hastNext() {
return currentGeneration != 0;
}
}
}
客戶端
public class Client {
public static void main(String[] args) {
FamilyAggregate family = new FamilyAggregateImpl(3);
family.addFamily(1, "曉月");
family.addFamily(2, "爸爸");
family.addFamily(2, "媽媽");
family.addFamily(2, "叔叔");
family.addFamily(2, "嬸嬸");
family.addFamily(3, "爺爺");
family.addFamily(3, "奶奶 ");
NameIterator iterator = family.createIterator();
while (iterator.hastNext()) {
String name = iterator.next();
System.out.println(name);
}
}
}
結果如下:
爺爺
奶奶
爸爸
媽媽
叔叔
嬸嬸
曉月
使用場景
- 1、訪問一個聚合對象的內容而無須暴露它的內部表示。
- 2、可以為聚合對象提供多種遍歷方式,比如順序、逆序等。
- 3、為遍歷不同的聚合結構提供一個統一的接口,比如訪問下一個元素的方法是next。
優點
- 1、它支持以不同的方式遍歷一個聚合對象。
- 2、迭代器簡化了聚合類。
- 3、在同一個聚合上可以有多個遍歷。
- 4、在迭代器模式中,增加新的聚合類和迭代器類都很方便,無須修改原有代碼。
缺點
- 由於迭代器模式將存儲數據和遍歷數據的職責分離,增加新的聚合類需要對應增加新的迭代器類,類的個數成對增加,這在一定程度上增加了系統的復雜性。
總結
迭代器模式應該是最常見的設計模式了,可以說Java程序員只要開發,都要使用它。
迭代器模式是一種行為型設計模式,它為集合提供了一個遍歷元素的方式,又不會暴露它的內部表示。
完
2021年12月7日01:47:38