鍍金池/ 教程/ Java/ 樹形結(jié)構(gòu)的處理——組合模式(三)
不兼容結(jié)構(gòu)的協(xié)調(diào)——適配器模式(三)
處理多維度變化——橋接模式(二)
擴(kuò)展系統(tǒng)功能——裝飾模式(四)
<code>C#</code> 設(shè)計模式之代理模式(四)
擴(kuò)展系統(tǒng)功能——裝飾模式(二)
實現(xiàn)對象的復(fù)用——享元模式(四)
實現(xiàn)對象的復(fù)用——享元模式(五)
處理多維度變化——橋接模式(三)
深入淺出外觀模式(二)
樹形結(jié)構(gòu)的處理——組合模式(二)
處理多維度變化——橋接模式(一)
<code>C#</code> 設(shè)計模式之代理模式(二)
不兼容結(jié)構(gòu)的協(xié)調(diào)——適配器模式(二)
深入淺出外觀模式(三)
實現(xiàn)對象的復(fù)用——享元模式(三)
不兼容結(jié)構(gòu)的協(xié)調(diào)——適配器模式(四)
樹形結(jié)構(gòu)的處理——組合模式(一)
擴(kuò)展系統(tǒng)功能——裝飾模式(三)
深入淺出外觀模式(一)
處理多維度變化——橋接模式(四)
樹形結(jié)構(gòu)的處理——組合模式(五)
擴(kuò)展系統(tǒng)功能——裝飾模式(一)
不兼容結(jié)構(gòu)的協(xié)調(diào)——適配器模式(一)
實現(xiàn)對象的復(fù)用——享元模式(二)
樹形結(jié)構(gòu)的處理——組合模式(三)
<code>C#</code> 設(shè)計模式之代理模式(一)
實現(xiàn)對象的復(fù)用——享元模式(一)
樹形結(jié)構(gòu)的處理——組合模式(四)
<code>C#</code> 設(shè)計模式之代理模式(三)

樹形結(jié)構(gòu)的處理——組合模式(三)

完整解決方案

為了讓系統(tǒng)具有更好的靈活性和可擴(kuò)展性,客戶端可以一致地對待文件和文件夾,Sunny 公司開發(fā)人員使用組合模式來進(jìn)行殺毒軟件的框架設(shè)計,其基本結(jié)構(gòu)如圖所示:

http://wiki.jikexueyuan.com/project/design-pattern-structurized/images/1347030143_6150.jpg" alt="殺毒軟件框架設(shè)計結(jié)構(gòu)圖" />

在圖中, AbstractFile 充當(dāng)抽象構(gòu)件類,F(xiàn)older 充當(dāng)容器構(gòu)件類,ImageFile、TextFile 和 VideoFile 充當(dāng)葉子構(gòu)件類。完整代碼如下所示:

import java.util.*;

//抽象文件類:抽象構(gòu)件
abstract class AbstractFile {
    public abstract void add(AbstractFile file);
    public abstract void remove(AbstractFile file);
    public abstract AbstractFile getChild(int i);
    public abstract void killVirus();
}

//圖像文件類:葉子構(gòu)件
class ImageFile extends AbstractFile {
    private String name;

    public ImageFile(String name) {
        this.name = name;
    }

    public void add(AbstractFile file) {
       System.out.println("對不起,不支持該方法!");
    }

    public void remove(AbstractFile file) {
        System.out.println("對不起,不支持該方法!");
    }

    public AbstractFile getChild(int i) {
        System.out.println("對不起,不支持該方法!");
        return null;
    }

    public void killVirus() {
        //模擬殺毒
        System.out.println("----對圖像文件'" + name + "'進(jìn)行殺毒");
    }
}

//文本文件類:葉子構(gòu)件
class TextFile extends AbstractFile {
    private String name;

    public TextFile(String name) {
        this.name = name;
    }

    public void add(AbstractFile file) {
       System.out.println("對不起,不支持該方法!");
    }

    public void remove(AbstractFile file) {
        System.out.println("對不起,不支持該方法!");
    }

    public AbstractFile getChild(int i) {
        System.out.println("對不起,不支持該方法!");
        return null;
    }

    public void killVirus() {
        //模擬殺毒
        System.out.println("----對文本文件'" + name + "'進(jìn)行殺毒");
    }
}

//視頻文件類:葉子構(gòu)件
class VideoFile extends AbstractFile {
    private String name;

    public VideoFile(String name) {
        this.name = name;
    }

    public void add(AbstractFile file) {
       System.out.println("對不起,不支持該方法!");
    }

    public void remove(AbstractFile file) {
        System.out.println("對不起,不支持該方法!");
    }

    public AbstractFile getChild(int i) {
        System.out.println("對不起,不支持該方法!");
        return null;
    }

    public void killVirus() {
        //模擬殺毒
        System.out.println("----對視頻文件'" + name + "'進(jìn)行殺毒");
    }
}

//文件夾類:容器構(gòu)件
class Folder extends AbstractFile {
    //定義集合fileList,用于存儲AbstractFile類型的成員
    private ArrayList<AbstractFile> fileList=new ArrayList<AbstractFile>();
    private String name;

    public Folder(String name) {
        this.name = name;
    }

    public void add(AbstractFile file) {
       fileList.add(file);  
    }

    public void remove(AbstractFile file) {
        fileList.remove(file);
    }

    public AbstractFile getChild(int i) {
        return (AbstractFile)fileList.get(i);
    }

    public void killVirus() {
        System.out.println("****對文件夾'" + name + "'進(jìn)行殺毒");  //模擬殺毒

        //遞歸調(diào)用成員構(gòu)件的killVirus()方法
        for(Object obj : fileList) {
            ((AbstractFile)obj).killVirus();
        }
    }
}

編寫如下客戶端測試代碼:

class Client {
    public static void main(String args[]) {
        //針對抽象構(gòu)件編程
        AbstractFile file1,file2,file3,file4,file5,folder1,folder2,folder3,folder4;

        folder1 = new Folder("Sunny的資料");
        folder2 = new Folder("圖像文件");
        folder3 = new Folder("文本文件");
        folder4 = new Folder("視頻文件");

        file1 = new ImageFile("小龍女.jpg");
        file2 = new ImageFile("張無忌.gif");
        file3 = new TextFile("九陰真經(jīng).txt");
        file4 = new TextFile("葵花寶典.doc");
        file5 = new VideoFile("笑傲江湖.rmvb");

        folder2.add(file1);
        folder2.add(file2);
        folder3.add(file3);
        folder3.add(file4);
        folder4.add(file5);
        folder1.add(folder2);
        folder1.add(folder3);
        folder1.add(folder4);

        //從“Sunny的資料”節(jié)點開始進(jìn)行殺毒操作
        folder1.killVirus();
    }
}

編譯并運(yùn)行程序,輸出結(jié)果如下:

****對文件夾'Sunny的資料'進(jìn)行殺毒
****對文件夾'圖像文件'進(jìn)行殺毒
----對圖像文件'小龍女.jpg'進(jìn)行殺毒
----對圖像文件'張無忌.gif'進(jìn)行殺毒
****對文件夾'文本文件'進(jìn)行殺毒
----對文本文件'九陰真經(jīng).txt'進(jìn)行殺毒
----對文本文件'葵花寶典.doc'進(jìn)行殺毒
****對文件夾'視頻文件'進(jìn)行殺毒
----對視頻文件'笑傲江湖.rmvb'進(jìn)行殺毒

由于在本實例中使用了組合模式,在抽象構(gòu)件類中聲明了所有方法,包括用于管理和訪問子構(gòu)件的方法,如 add() 方法和 remove() 方法等,因此在 ImageFile 等葉子構(gòu)件類中實現(xiàn)這些方法時必須進(jìn)行相應(yīng)的異常處理或錯誤提示。在容器構(gòu)件類 Folder 的 killVirus() 方法中將遞歸調(diào)用其成員對象的 killVirus() 方法,從而實現(xiàn)對整個樹形結(jié)構(gòu)的遍歷。

如果需要更換操作節(jié)點,例如只需對文件夾“文本文件”進(jìn)行殺毒,客戶端代碼只需修改一行即可,將代碼: folder1.killVirus();
改為:
folder3.killVirus();

輸出結(jié)果如下:

****對文件夾'文本文件'進(jìn)行殺毒
----對文本文件'九陰真經(jīng).txt'進(jìn)行殺毒
----對文本文件'葵花寶典.doc'進(jìn)行殺毒

在具體實現(xiàn)時,我們可以創(chuàng)建圖形化界面讓用戶選擇所需操作的根節(jié)點,無須修改源代碼,符合“開閉原則”,客戶端無須關(guān)心節(jié)點的層次結(jié)構(gòu),可以對所選節(jié)點進(jìn)行統(tǒng)一處理,提高系統(tǒng)的靈活性。