## 一、模式動機 迭代器模式(Iterator Pattern)是一種使用頻率非常高的行為型設計模式,**迭代器**用於**對一個聚合對象進行遍歷**。通過**引入迭代器**可以**將數據的遍歷功能從聚合對象中分離出來**,**聚合對象只負責存儲數據**,而**遍曆數據由迭代器來完成**,簡化了聚 ...
一、模式動機
迭代器模式(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