遍歷聚合物件中的元素——迭代器模式(三)
3 完整解決方案
為了簡化AbstractObjectList類的結構,並給不同的具體資料集合類提供不同的遍歷方式,Sunny軟體公司開發人員使用迭代器模式來重構AbstractObjectList類的設計,重構之後的銷售管理系統資料遍歷結構如圖4所示:
圖4 銷售管理系統資料遍歷結構圖
(注:為了簡化類圖和程式碼,本結構圖中只提供一個具體聚合類和具體迭代器類)
在圖4中,AbstractObjectList充當抽象聚合類,ProductList充當具體聚合類,AbstractIterator充當抽象迭代器,ProductIterator充當具體迭代器。完整程式碼如下所示:
//在本例項中,為了詳細說明自定義迭代器的實現過程,我們沒有使用JDK中內建的迭代器,事實上,JDK內建迭代器已經實現了對一個List物件的正向遍歷
import java.util.*;
//抽象聚合類
abstract class AbstractObjectList {
protected List<Object> objects = new ArrayList<Object>();
public AbstractObjectList(List objects) {
this.objects = objects;
}
public void addObject(Object obj) {
this.objects.add(obj);
}
public void removeObject(Object obj) {
this.objects.remove(obj);
}
public List getObjects() {
return this.objects;
}
//宣告建立迭代器物件的抽象工廠方法
public abstract AbstractIterator createIterator();
}
//商品資料類:具體聚合類
class ProductList extends AbstractObjectList {
public ProductList(List products) {
super(products);
}
//實現建立迭代器物件的具體工廠方法
public AbstractIterator createIterator() {
return new ProductIterator(this);
}
}
//抽象迭代器
interface AbstractIterator {
public void next(); //移至下一個元素
public boolean isLast(); //判斷是否為最後一個元素
public void previous(); //移至上一個元素
public boolean isFirst(); //判斷是否為第一個元素
public Object getNextItem(); //獲取下一個元素
public Object getPreviousItem(); //獲取上一個元素
}
//商品迭代器:具體迭代器
class ProductIterator implements AbstractIterator {
private ProductList productList;
private List products;
private int cursor1; //定義一個遊標,用於記錄正向遍歷的位置
private int cursor2; //定義一個遊標,用於記錄逆向遍歷的位置
public ProductIterator(ProductList list) {
this.productList = list;
this.products = list.getObjects(); //獲取集合物件
cursor1 = 0; //設定正向遍歷遊標的初始值
cursor2 = products.size() -1; //設定逆向遍歷遊標的初始值
}
public void next() {
if(cursor1 < products.size()) {
cursor1++;
}
}
public boolean isLast() {
return (cursor1 == products.size());
}
public void previous() {
if (cursor2 > -1) {
cursor2--;
}
}
public boolean isFirst() {
return (cursor2 == -1);
}
public Object getNextItem() {
return products.get(cursor1);
}
public Object getPreviousItem() {
return products.get(cursor2);
}
}
編寫如下客戶端測試程式碼:
class Client {
public static void main(String args[]) {
List products = new ArrayList();
products.add("倚天劍");
products.add("屠龍刀");
products.add("斷腸草");
products.add("葵花寶典");
products.add("四十二章經");
AbstractObjectList list;
AbstractIterator iterator;
list = new ProductList(products); //建立聚合物件
iterator = list.createIterator(); //建立迭代器物件
System.out.println("正向遍歷:");
while(!iterator.isLast()) {
System.out.print(iterator.getNextItem() + ",");
iterator.next();
}
System.out.println();
System.out.println("-----------------------------");
System.out.println("逆向遍歷:");
while(!iterator.isFirst()) {
System.out.print(iterator.getPreviousItem() + ",");
iterator.previous();
}
}
}
編譯並執行程式,輸出結果如下:
正向遍歷: 倚天劍,屠龍刀,斷腸草,葵花寶典,四十二章經, ----------------------------- 逆向遍歷: 四十二章經,葵花寶典,斷腸草,屠龍刀,倚天劍, |
如果需要增加一個新的具體聚合類,如客戶資料集合類,並且需要為客戶資料集合類提供不同於商品資料集合類的正向遍歷和逆向遍歷操作,只需增加一個新的聚合子類和一個新的具體迭代器類即可,原有類庫程式碼無須修改,符合“開閉原則”;如果需要為ProductList類更換一個迭代器,只需要增加一個新的具體迭代器類作為抽象迭代器類的子類,重新實現遍歷方法,原有迭代器程式碼無須修改,也符合“開閉原則”;但是如果要在迭代器中增加新的方法,則需要修改抽象迭代器原始碼,這將違背“開閉原則”。
【作者:劉偉 http://blog.csdn.net/lovelion】
相關文章
- 遍歷聚合物件中的元素——迭代器模式(四)物件模式
- 設計模式系列之迭代器模式(Iterator Pattern)——遍歷聚合物件中的元素設計模式物件
- 讓Vue的v-for支援迭代器遍歷Vue
- 如何遍歷Map中的物件物件
- DOM元素的遍歷
- 關於二叉樹的前序遍歷、中序遍歷、刪除元素、插入元素二叉樹
- for in語句遍歷陣列中的元素陣列
- js如何遍歷陣列中的元素JS陣列
- C++11::遍歷tuple中的元素C++
- 不用for迭代 --手工訪問迭代器中的元素.
- jQuery 元素操作——遍歷元素jQuery
- 三種騷操作繞過迭代器遍歷時的資料修改異常
- Jvascript陣列迭代,遍歷的方法陣列
- 94. 二叉樹的中序遍歷(迭代)二叉樹
- JS 物件的遍歷JS物件
- JS中遍歷陣列、物件的方式JS陣列物件
- Jquery之遍歷元素jQuery
- JavaScript 遍歷、列舉與迭代JavaScript
- 【Java中遍歷Map物件的4種方法】Java物件
- JS遍歷物件的方式JS物件
- 深入JS物件的遍歷JS物件
- jquery中each的三種遍歷方法jQuery
- vector容器1(新增元素,遍歷元素)
- javascript如何遍歷陣列中的每一個元素JavaScript陣列
- 你知道JavaScript中的可迭代物件與迭代器嗎JavaScript物件
- 二叉樹的遍歷 (迭代法)二叉樹
- jquery遍歷子元素的寫法jQuery
- vue遍歷map物件Vue物件
- thymeleaf模板 遍歷物件物件
- Qt遍歷子物件QT物件
- 遍歷陣列物件陣列物件
- Java中如何遍歷Map物件的4種方法Java物件
- JavaScript遍歷物件的屬性JavaScript物件
- 常見物件-字串的遍歷物件字串
- 物件和陣列的遍歷物件陣列
- 為什麼for迴圈可以遍歷list:Python中迭代器與生成器Python
- 遍歷List 同時 remove 元素REM
- jQuery遍歷函式,javascript中的each遍歷jQuery函式JavaScript