場景一
描述:週五下午,我正在看技術網站,第六感官發覺有人在身後,扭頭一看,我C,老大站在背後,趕忙站起來,
“王經理,你找我?” 我說。
“哦,在看技術呀。有個事情找你談一下,你到我辦公室來一下。” 老大說。
到老大辦公室,
“是這樣,剛剛我在看季報,我們每個項目的支出費用都很高,項目情況複雜,人員情況也不簡單,我看着也有點糊塗,你看,這是我們現在還在開發或者維護的103 個項目,你能不能先把這些項目信息重新打印一份給我,咱們好查查到底有什麼問題。”老大說。“這個好辦,我馬上去辦”我爽快的答覆道。
很快我設計了一個類圖,並開始實施:
類圖非常簡單,是個程序員都能實現,我們來看看簡單的東西:
package com.gumx;
/**
* @author gumx
* I'm glad to share my knowledge with you all.
* 定義一個接口,所有的項目都是一個接口
*/
public interface IProject {
//從老闆這裏看到的就是項目信息
public String getProjectInfo();
}
定義了一個接口,面向接口編程嘛,當然要定義接口了,然後看看實現類:
package com.gumx;
/**
* @author gumx
* I'm glad to share my knowledge with you all.
* 所有項目的信息類
*/
public class Project implements IProject {
//項目名稱
private String name = "";
//項目成員數量
private int num = 0;
//項目費用
private int cost = 0;
//定義一個構造函數,把所有老闆需要看到的信息存儲起來
public Project(String name,int num,int cost){
//賦值到類的成員變量中
this.name = name;
this.num = num;
this.cost=cost;
}
//得到項目的信息
public String getProjectInfo() {
String info = "";
//獲得項目的名稱
info = info+ "項目名稱是:" + this.name;
//獲得項目人數
info = info + "\t項目人數: "+ this.num;
//項目費用
info = info+ "\t 項目費用:"+ this.cost;
return info;
}
}
實現類也是比較簡單的,通過構造函數傳遞過來要顯示的數據,然後放到getProjectInfo 中顯示,這太easy 了!,然後我們老大要看看結果了:
package com.gumx;
import java.util.ArrayList;
/**
* @author gumx
* I'm glad to share my knowledge with you all.
* 老闆來看項目信息了
*/
public class Boss {
public static void main(String[] args) {
//定義一個List,存放所有的項目對象
ArrayList<IProject> projectList = new ArrayList<IProject>();
//增加星球大戰項目
projectList.add(new Project("星球大戰項目",10,100000));
//增加扭轉時空項目
projectList.add(new Project("扭轉時空項目",100,10000000));
//增加超人改造項目
projectList.add(new Project("超人改造項目",10000,1000000000));
//這邊100個項目
for(int i=4;i<104;i++){
projectList.add(new Project("第"+i+"個項目",i*5,i*1000000));
}
//遍歷一下ArrayList,把所有的數據都取出
for(IProject project:projectList){
System.out.println(project.getProjectInfo());
}
}
}
然後看一下我們的運行結果:
項目名稱是:星球大戰項目項目人數: 10 項目費用:100000
項目名稱是:扭轉時空項目項目人數: 100 項目費用:10000000
項目名稱是:超人改造項目項目人數: 10000 項目費用:1000000000
項目名稱是:第4個項目項目人數: 20 項目費用:4000000
項目名稱是:第5個項目項目人數: 25 項目費用:5000000
.
.
.
老大一看,非常Happy,這麼快就出結果了,大大的把我誇獎了一番,然後就去埋頭去研究那堆枯燥的報表了,然後我回到座位上,又看了一遍程序(心裏很樂,就又想看看自己的成果),想想了,應該還有另外一種實現方式,因爲是遍歷嘛,讓我想到的就是迭代器模式,我先把類圖畫出來:
看着是不是複雜了很多?是的,是有點複雜了,這個我等會說明原因,我們看代碼實現,先IProject 接口:
package com.gumx.pattern;
/**
* @author gumx
* I'm glad to share my knowledge with you all.
* 定義一個接口,所有的項目都是一個接口
*/
public interface IProject {
//增加項目
public void add(String name,int num,int cost);
//從老闆這裏看到的就是項目信息
public String getProjectInfo();
//獲得一個可以被遍歷的對象
public IProjectIterator iterator();
}
這裏多了兩個方法,一個是add 方法,這個方法是增加項目,也就是說產生了一個對象後,直接使用add方法增加項目信息。我們再來看實現類:
package com.gumx.pattern;
import java.util.ArrayList;
/**
* @author gumx
* I'm glad to share my knowledge with you all.
* 所有項目的信息類
*/
@SuppressWarnings("all")
public class Project implements IProject {
//定義一個項目列表,說有的項目都放在這裏
private ArrayList<IProject> projectList = new ArrayList<IProject>();
//項目名稱
private String name = "";
//項目成員數量
private int num = 0;
//項目費用
private int cost = 0;
public Project(){
}
//定義一個構造函數,把所有老闆需要看到的信息存儲起來
private Project(String name,int num,int cost){
//賦值到類的成員變量中
this.name = name;
this.num = num;
this.cost=cost;
}
//增加項目
public void add(String name,int num,int cost){
this.projectList.add(new Project(name,num,cost));
}
//得到項目的信息
public String getProjectInfo() {
String info = "";
//獲得項目的名稱
info = info+ "項目名稱是:" + this.name;
//獲得項目人數
info = info + "\t項目人數: "+ this.num;
//項目費用
info = info+ "\t 項目費用:"+ this.cost;
return info;
}
//產生一個遍歷對象
public IProjectIterator iterator(){
return new ProjectIterator(this.projectList);
}
}
項目信息類已經產生,我們再來看看我們的迭代器是如何實現的,先看接口:
package com.gumx.pattern;
import java.util.Iterator;
/**
* @author gumx
* I'm glad to share my knowledge with you all.
* 定義個Iterator接口
*/
@SuppressWarnings("all")
public interface IProjectIterator extends Iterator {
}
大家可能很奇怪,你定義的這個接口方法、變量都沒有,有什麼意義呢?有意義,所有的Java 書上都一直說是面向接口編程,你的接口是對一個事物的描述,也就是說我通過接口就知道這個事物有哪些方法,哪些屬性,我們這裏的IProjectIterator
是要建立一個指向Project 類的迭代器,目前暫時定義的就是一個通用的迭代器,可能以後會增加IProjectIterator 的一些屬性或者方法。當然了,你也可以在實現類上實現兩個接口,一個是Iterator,一個是IProjectIterator(這時候,這個接口就不用繼承Iterator),殺豬殺尾巴,各有各的殺發。我的習慣是:如果我要實現一個容器或者其他API 提供接口時,我一般都自己先寫一個接口繼承,然後再繼承自己寫的接口,保證自己的實現類只用實現自己寫的接口(接口傳遞,當然也要實現頂層的接口),程序閱讀也清晰一些。我們繼續看迭代器的實現類:
package com.gumx.pattern;
import java.util.ArrayList;
/**
* @author gumx
* I'm glad to share my knowledge with you all.
* 定義一個迭代器
*/
public class ProjectIterator implements IProjectIterator {
//所有的項目都放在這裏ArrayList中
private ArrayList<IProject> projectList = new ArrayList<IProject>();
private int currentItem = 0;
//構造函數傳入projectList
public ProjectIterator(ArrayList<IProject> projectList){
this.projectList = projectList;
}
//判斷是否還有元素,必須實現
public boolean hasNext() {
//定義一個返回值
boolean b = true;
if(this.currentItem>=projectList.size() ||
this.projectList.get(this.currentItem) == null){
b =false;
}
return b;
}
//取得下一個值
public IProject next() {
return (IProject)this.projectList.get(this.currentItem++);
}
//刪除一個對象
public void remove() {
//暫時沒有使用到
}
}
都寫完畢了,然後看看我們的Boss 類有多少改動:
package com.gumx.pattern;
/**
* @author gumx
* I'm glad to share my knowledge with you all.
* 老闆來看項目信息了
*/
public class Boss {
public static void main(String[] args) {
//定義一個List,存放所有的項目對象
IProject project = new Project();
//增加星球大戰項目
project.add("星球大戰項目ddddd",10,100000);
//增加扭轉時空項目
project.add("扭轉時空項目",100,10000000);
//增加超人改造項目
project.add("超人改造項目",10000,1000000000);
//這邊100個項目
for(int i=4;i<104;i++){
project.add("第"+i+"個項目",i*5,i*1000000);
}
//遍歷一下ArrayList,把所有的數據都取出
IProjectIterator projectIterator = project.iterator();
while(projectIterator.hasNext()){
IProject p = (IProject)projectIterator.next();
System.out.println(p.getProjectInfo());
}
}
}
運行結果如下:
項目名稱是:星球大戰項目項目人數: 10 項目費用:100000
項目名稱是:扭轉時空項目項目人數: 100 項目費用:10000000
項目名稱是:超人改造項目項目人數: 10000 項目費用:1000000000
項目名稱是:第4個項目項目人數: 20 項目費用:4000000
項目名稱是:第5個項目項目人數: 25 項目費用:5000000
.
.
.
上面的程序增加了複雜性,但是從面向對象的開發上來看,project.add()增加一個項目是不是更友好一些?
上面的例子就使用了迭代器模式,我們來看看迭代器的通用類圖:
類圖是很簡單,但是你看用起來就很麻煩,就比如上面例子的兩個實現方法,你覺的那個簡單?當然是第一個了!23 個設計模式是爲了簡化我們代碼和設計的複雜度、耦合程度,爲什麼我們用了這個迭代器模式程序會複雜了一些呢?這是爲什麼?因爲從JDK 1.2 版本開始增加java.util.Iterator 這個接口,並逐步把Iterator 應用到各個聚集類(Collection)中,我們來看JDK 1.5 的API 幫助文件,你會看到有一個叫java.util.Iterable 的接口,看看有多少個接口繼承了它:
java.util.Iterable 接口只有一個方法:iterator(),也就說通過iterator()這個方法去遍歷聚集類中的所有方法或屬性,基本上現在所有的高級的語言都有Iterator 這個接口或者實現,Java 已經把迭代器給我們準備了,我們再去寫迭代器,是不是“六指兒抓癢,多一道子”?所以呀,這個迭代器模式也有點沒落了,基本上很少有項目再獨立寫迭代器了,直接使用List 或者Map 就可以完整的解決問題。