Java設計模式——迭代器模式(Iterator Pattern)

場景一

描述:週五下午,我正在看技術網站,第六感官發覺有人在身後,扭頭一看,我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 就可以完整的解決問題。







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章