一、模式動機
迭代器模式(Iterator Pattern)是一種使用頻率非常高的行為型設計模式,迭代器用于對一個聚合物件進行遍歷,通過引入迭代器可以將資料的遍歷功能從聚合物件中分離出來,聚合物件只負責存盤資料,而遍歷資料由迭代器來完成,簡化了聚合物件的設計,更符合“單一職責原則”的要求,Java語言提供了對迭代器模式的完美支持,通常我們不需要自己定義新的迭代器,直接使用Java提供的迭代器即可,迭代器模式又稱為“游標(Cursor)模式”,它是一種物件行為型模式,
類比:
- 電視機 ? ? 存盤電視頻道的集合 ? ? 聚合類(Aggregate Classes)
- 電視機遙控器 ? ? 操作電視頻道 ? ? 迭代器(Iterator)
- 如何訪問一個聚合物件中的元素但又不需要暴露它的內部結構,還能提供多種不同的遍歷方式 ? ? 迭代器模式
二、模式定義
- 迭代器模式(Iterator Pattern) :提供一種方法來訪問聚合物件,而不用暴露這個物件的內部表示,
- 提供一個外部的迭代器對聚合物件進行訪問和遍歷,迭代器中定義了一個訪問該聚合物件的介面,并且可以跟蹤當前遍歷的元素,了解哪些元素已經遍歷,哪些沒有,
- 其別名為游標(Cursor)
- 迭代器模式是一種物件行為型模式
三、模式結構

抽象迭代器類
public interface Iterator {
public void first(); //將游標指向第一個元素
public void next(); //將游標指向下一個元素
public boolean hasNext(); //判斷是否存在下一個元素
public Object currentItem(); //獲取游標指向的當前元素
}
具體迭代器類
public class ConcreteIterator implements Iterator {
private ConcreteAggregate objects; //維持一個對具體聚合物件的參考,以便于訪問存盤在聚合物件中的資料
private int cursor; //定義一個游標,用于記錄當前訪問位置
public ConcreteIterator(ConcreteAggregate objects) {
this.objects=objects;
}
public void first() { ...... }
public void next() { ...... }
public boolean hasNext( ) { ...... }
public Object currentItem( ) { ...... }
}
抽象聚合類
public interface Aggregate {
Iterator createIterator( );
}
具體聚合類
public class ConcreteAggregate implements Aggregate {
......
public Iterator createIterator( ) {
return new ConcreteIterator(this);
}
......
}
四、案例實作
案例背景
遙控操控電視頻道遍歷
案例結構

代碼實作
抽象迭代器類:電視機遙控器類
public interface TVInterator {
void setChannel(int i);
Object currentChannel();
void next();
void previous();
boolean isLast();
boolean isFirst();
}
抽象聚合類
public interface Television {
TVInterator createInterator();
}
具體電視機類:創維電視機類
public class SkyworthTelevision implements Television{
private Object[] obj = {"CCTV-1","CCTV-2","CCTV-3","CCTV-4","CCTV-5","CCTV-6"};
@Override
public TVInterator createInterator() {
return new SkyworthInterator(obj);
}
}
具體電視機類:TCL
public class TCLTelevision implements Television{
private Object[] obj = {"湖南衛視","上海衛視","山西衛視","河北衛視","上海衛視","北京衛視"};
@Override
public TVInterator createInterator() {
return new SkyworthInterator(obj);
}
}
具體電視機遙控器類:創維
public class SkyworthInterator implements TVInterator{
private int currentIndex = 0;
private Object obj[];
public SkyworthInterator(Object[] obj) {
this.obj = obj;
}
@Override
public void setChannel(int i) {
currentIndex = i;
}
@Override
public Object currentChannel() {
return obj[currentIndex];
}
@Override
public void next() {
if (currentIndex < obj.length){
currentIndex ++;
}
}
@Override
public void previous() {
if (currentIndex > 0){
currentIndex --;
}
}
@Override
public boolean isLast() {
return currentIndex == obj.length;
}
@Override
public boolean isFirst() {
return currentIndex ==0;
}
}
具體電視機遙控器類:TCL
public class TCLInterator implements TVInterator{
private int currentIndex = 0;
private Object obj[];
public TCLInterator(Object[] obj) {
this.obj = obj;
}
@Override
public void setChannel(int i) {
currentIndex = i;
}
@Override
public Object currentChannel() {
return obj[currentIndex];
}
@Override
public void next() {
if (currentIndex < obj.length){
currentIndex ++;
}
}
@Override
public void previous() {
if (currentIndex > 0){
currentIndex --;
}
}
@Override
public boolean isLast() {
return currentIndex == obj.length;
}
@Override
public boolean isFirst() {
return currentIndex ==0;
}
}
客戶類
public class Client {
public static void display(Television tv){
TVInterator interator = tv.createInterator();
System.out.println("電視機頻道:");
while (!interator.isLast()){
System.out.println(interator.currentChannel().toString());
interator.next();
}
}
public static void reverseDisplay(Television tv){
TVInterator interator = tv.createInterator();
interator.setChannel(6);
System.out.println("逆向遍歷電視機頻道:");
while (!interator.isFirst()){
interator.previous();
System.out.println(interator.currentChannel().toString());
}
}
public static void main(String a[]) {
Television tv = (Television) XMLUtil.getBean();
display(tv);
System.out.println("===============");
reverseDisplay(tv);
}
}
案例分析
- 如果需要增加一個新的具體聚合類,只需增加一個新的聚合子類和一個新的具體迭代器類即可,原有類別庫代碼無須修改,符合開閉原則
- 如果需要更換一個迭代器,只需要增加一個新的具體迭代器類作為抽象迭代器類的子類,重新實作遍歷方法即可,原有迭代器代碼無須修改,也符合開閉原則
- 如果要在迭代器中增加新的方法,則需要修改抽象迭代器的源代碼,這將違背開閉原則
五、模式分析
- 聚合物件的兩個職責:
- 存盤資料,聚合物件的基本職責
- 遍歷資料,既是可變化的,又是可分離的
- 將遍歷資料的行為從聚合物件中分離出來,封裝在迭代器物件中
- 由迭代器來提供遍歷聚合物件內部資料的行為,簡化聚合物件的設計,更符合單一職責原則
六、總結
模式優點
- 支持以不同的方式遍歷一個聚合物件,在同一個聚合物件上可以定義多種遍歷方式
- 簡化了聚合類
- 由于引入了抽象層,增加新的聚合類和迭代器類都很方便,無須修改原有代碼,符合開閉原則
模式缺點
- 在增加新的聚合類時需要對應地增加新的迭代器類,類的個數成對增加,這在一定程度上增加了系統的復雜性
- 抽象迭代器的設計難度較大,需要充分考慮到系統將來的擴展,在自定義迭代器時,創建一個考慮全面的抽象迭代器并不是一件很容易的事情
使用情形
- 訪問一個聚合物件的內容而無須暴露它的內部表示
- 需要為一個聚合物件提供多種遍歷方式
- 為遍歷不同的聚合結構提供一個統一的介面,在該介面的實作類中為不同的聚合結構提供不同的遍歷方式,而客戶端可以一致性地操作該介面
本文來自博客園,作者:街酒,轉載請注明原文鏈接:https://www.cnblogs.com/sorrymine/p/17421409.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/553126.html
標籤:設計模式
下一篇:返回列表
