遍歷聚合物件中的元素——迭代器模式(三)

Liuwei-Sunny發表於2013-08-15

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

相關文章