設計模式解密(10)-迭代器模式
定義:提供一種方法順序訪問一個聚合對象中各個元素, 而又無須暴露該對象的內部表示;
主要用途:幫助我們遍歷聚合對象;
關鍵代碼:定義介面:hasNext, next;
英文:Iterator
類型:行為型模式
2、類圖及組成(引)類圖:
組成:
抽象容器:一般是一個介面,提供一個iterator方法,例如java中的Collection介面,List介面,Set介面等。
具體容器:就是抽象容器的具體實現類,比如List介面的有序列表實現ArrayList,List介面的鏈表實現LinkList,Set介面的哈希列表的實現HashSet等。
抽象迭代器:定義遍曆元素所需要的方法,一般來說會有這麼三個方法:取得第一個元素的方法first,取得下一個元素的方法next,判斷是否遍歷結束的方法hasNext,移出當前對象的方法remove,
迭代器實現:實現迭代器介面中定義的方法,完成集合的迭代。
3、實例引入模擬一下迭代器的簡單實現:
package com.designpattern.iterator;
/**
* 抽象迭代器介面
* @author Json
*/
public interface Iterator {
public boolean hasNext;
public Object next;
}
package com.designpattern.iterator;
import java.util.ArrayList;
/**
* 具體迭代器實現
* @author Json
*/
public class ConcreteIterator implements Iterator {
private ArrayList list = new ArrayList;
private int cursor = 0;
public ConcreteIterator(ArrayList list) {
this.list = list;
}
@Override
public boolean hasNext {
if(cursor == list.size){
return false;
}
return true;
}
@Override
public Object next {
if(this.hasNext){
return this.list.get(cursor++);
}
return null;
}
}
package com.designpattern.iterator;
/**
* 抽象容器
* @author Json
*/
public interface Aggregate {
public void add(Object obj);
public void remove(Object obj);
public Iterator iterator;
}
package com.designpattern.iterator;
import java.util.ArrayList;
/**
* 具體容器
* @author Json
*/
public class ConcreteAggregate implements Aggregate {
private ArrayList list = new ArrayList;
@Override
public void add(Object obj) {
list.add(obj);
}
@Override
public void remove(Object obj) {
list.remove(obj);
}
@Override
public Iterator iterator {
return new ConcreteIterator(list);
}
}
測試:
package com.designpattern.iterator;
/**
* 測試
* @author Json
*/
public class Test {
public static void main(String[] args) {
Aggregate agg = new ConcreteAggregate;
agg.add("Java");
agg.add("Ruby");
agg.add("Python");
Iterator iterator = agg.iterator;
while(iterator.hasNext){
String s = (String) iterator.next;
System.out.println(s);
}
}
}
結果:
Java
Ruby
Python
4、優缺點優點:
1、它支持以不同的方式遍歷一個聚合對象。
2、迭代器簡化了聚合類。
3、在同一個聚合上可以有多個遍歷。
4、在迭代器模式中,增加新的聚合類和迭代器類都很方便,無須修改原有代碼。
缺點:由於迭代器模式將存儲數據和遍曆數據的職責分離,增加新的聚合類需要對應增加新的迭代器類,類的個數成對增加,這在一定程度上增加了系統的複雜性。
5、應用場景
1、訪問一個聚合對象的內容而無須暴露它的內部表示。
2、需要為聚合對象提供多種遍歷方式。
3、為遍歷不同的聚合結構提供一個統一的介面。
6、JDK的迭代器應用JDK中就有大量迭代器的身影:
//java中迭代器介面源碼:
public interface Iterator
boolean hasNext;//判斷是否存在下一個對象元素
E next;
void remove;
}
迭代器模式與集合是緊密聯繫的,可以說密不可分,我們只要實現一個集合,就需要同時提供這個集合的迭代器,就像Java中的Collection,List、Set、Map等,這些集合都有自己的迭代器。假如我們要實現一個這樣的新的容器,當然也需要引入迭代器模式,給我們的容器實現一個迭代器。但是,由於容器與迭代器的關係太密切了,所以大多數語言在實現容器的時候都給提供了迭代器,並且這些語言提供的容器和迭代器在絕大多數情況下就可以滿足我們的需要,所以現在需要我們自己去實踐迭代器模式的場景還是比較少見的;
下面測試一下JDK迭代器的使用:
package com.designpattern.iterator.jdk_use_iterator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* 測試JDK自帶的迭代器
* @author Json
*/
public class IteratorTest {
public static void main(String[] args) {
List list = new ArrayList;
for(int i = 0;i < 10;i++){
list.add("list_"+i);
}
Iterator iterList = list.iterator;//List介面實現了Iterable介面
while(iterList.hasNext){
String str = (String)iterList.next;
System.out.print(str+"、");
}
System.out.println("");
Map map = new HashMap;
for(int i = 0;i < 10;i++){
map.put(i,"map_"+i);
}
Iterator iterMap = map.entrySet.iterator;
while(iterMap.hasNext){
Map.Entry strMap = (Map.Entry)iterMap.next;
System.out.print(strMap.getValue+"、");
}
}
}
結果:
list_0、list_1、list_2、list_3、list_4、list_5、list_6、list_7、list_8、list_9、
map_0、map_1、map_2、map_3、map_4、map_5、map_6、map_7、map_8、map_9、
7、迭代器與foreach
從Java5起,Java中新增foreach循環,關於foreach的語法,可以實現兩種數據類型的遍歷,一個是數組,一個便是實現了Iterable介面的任何類,今天不討論數組,我們主要關注實現了Iterable介面的類,是如何使用foreach遍歷的;
foreach循環允許你在無需保持傳統for循環中的索引,或在使用iterator時無需調用while循環中的hasNext方法就能遍歷Collection,foreach循環簡化了任何Collection或array的遍歷過程;
但是使用foreach循環也有兩點需要注意:
1、 foreach循環通過iterator實現,使用foreach循環的對象必須實現Iterable介面;
foreach循環只適用於實現了Iterable
但是在以後涉及到自定義聚合對象時,要注意這一點;
2、 在遍歷Collection時,如果要在遍歷期間修改或刪除Collection,則最好通過Iterator來實現,否則可能會發生「不確定的錯誤」。
附知識點: 在使用Java集合的時候,都需要使用 Iterator。但是java集合中還有一個迭代器ListIterator,在使用 List、ArrayList、LinkedList和 Vector的時候可以使用;
關於第二點測試例子:
package com.designpattern.iterator.jdk_use_iterator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
*
* @author Json
*/
public class IteratorTest1 {
public static void main(String[] args) {
Collection
list.add("張三");
list.add("李四");
list.add("王五");
list.add("趙六");
//removeItem1(list);
//removeItem2(list);
removeItem3(list);
}
/**
* 錯誤用法1
*/
public static void removeItem1(Collection
Iterator
while (iterator_1.hasNext) {
String str = iterator_1.next;
if("張三".equals(str)){
list.remove(str);
}
}
System.out.println(list);
}
/**
* 錯誤用法2
*/
public static void removeItem2(Collection
for (String str : list) {
if("張三".equals(str)){
list.remove(str);
}
}
System.out.println(list);
}
/** 8、總結 迭代器模式就是分離了集合對象的遍歷行為,抽象出一個迭代器類來負責,這樣既可以做到不暴露集合的內部結構,又可讓外部代碼透明地訪問集合內部的數據; 迭代器在平時需要我們自定義設計的情景不是很多,但是可能真會遇到這樣的需求,所以有必要知道它是怎麼實現的;
* 正確用法
*/
public static void removeItem3(Collection
Iterator
while (iterator_3.hasNext) {
String str = iterator_3.next;
if("張三".equals(str)){
iterator_3.remove;
}
}
System.out.println(list);
}
}
※阿里巴巴2018屆應屆生在線編程測驗-研發工程師C/C++
※Redis 錯誤1067:進程意外終止,Redis不能啟動,Redis啟動不了
※ASP.NET Core MVC 過濾器介紹
TAG:科技優家 |
※24種設計模式及案例
※小米平板4 MIUI10開始公測:支持1:2分屏模式
※一加5/5T正式推送安卓8.1:手勢、遊戲模式
※2018年聯合辦公運營模式及競爭格局分析
※設計模式之代理模式
※《生化危機2 重製版》支持4K或60幀 精簡戰役模式
※《萬象物語》挑戰模式t19打法心得 萬象物語挑戰模式t19
※體態代償模式的評估與康復 WH 北京7.5-8 上海7.12-15
※TGS 2018:《靈魂能力6》演示 展示靈魂解放模式
※工業4.0時代設備管理模式探討
※柯文哲複製「陳水扁模式」模式直攻2020?網友分析原因
※諾基亞2.1/3.1/5.1多款低端機發布:搭載安卓系統 恐複製小米模式
※PS4 Pro《戰神》將提供性能模式和4K模式
※2020年形成北京教育信息化發展新模式
※反射與代理設計模式-動態代理設計模式
※安川DX200安全模式的更改
※設計模式概念
※3.拍攝模式的布局
※12種駕駛模式!試駕全新BMW 530Le
※多種模式隨意切換 雷柏MT700三模辦公機械鍵盤評測