Java設(shè)計(jì)模式百例 - 合成模式

本文源碼見:https://github.com/get-set/get-designpatterns/tree/master/composite

組合模式(Composite Pattern)扼雏,又叫部分整體模式五垮,依據(jù)樹形結(jié)構(gòu)來組合對(duì)象诱贿,是用來表示部分以及整體層次的一種遞歸式結(jié)構(gòu)的模式寨躁。這種類型的設(shè)計(jì)模式屬于結(jié)構(gòu)型模式器联,它創(chuàng)建了對(duì)象組的樹形結(jié)構(gòu)柒室。

其實(shí)現(xiàn)實(shí)世界中甸饱,這種樹狀結(jié)構(gòu)的組合還是挺普遍的:

  1. 組織結(jié)構(gòu)耕皮,從CEO到基層組長(zhǎng)凯肋,都有下屬谊惭,他們都相當(dāng)于“枝干”,對(duì)于基層員工就是“葉子”節(jié)點(diǎn)侮东,不過說到底他們都是公司員工圈盔;
  2. 目錄結(jié)構(gòu),這個(gè)更好理解了悄雅,目錄里包含子目錄和文件驱敲,各層目錄相當(dāng)于樹狀結(jié)構(gòu)的“枝干”,文件相當(dāng)于“葉子”節(jié)點(diǎn)宽闲,說到底目錄和文件都是文件系統(tǒng)的組件(在Linux里众眨,都可以看作“文件”這個(gè)大的概念,甚至鼠標(biāo)鍵盤等設(shè)備)容诬;
  3. 一句文字娩梨,無論是書信還是微博,都是由字览徒、詞構(gòu)成的狈定,詞呢又是由字構(gòu)成的,字和詞都可以看作句子的組成元素习蓬,二者又有包含關(guān)系纽什。

看到這里是不是覺得已經(jīng)不用再看具體例子的代碼了呢,聰明的你估計(jì)腦海中已經(jīng)構(gòu)思除了一個(gè)小的demo了躲叼。

例子

就以文件系統(tǒng)目錄結(jié)構(gòu)為例吧稿湿。剛才說到,無論是目錄還是文件押赊,在Linux中我們都認(rèn)為是廣義的“文件”饺藤,為了方便闡述包斑,我們把這個(gè)廣義的“文件”叫做Entry吧,顯然目錄DirectoryFile都是一種Entry涕俗。如下:

Entry.java

public abstract class Entry {
    public abstract String getName();
    public abstract int getSize();
    public abstract Entry add(Entry entry) {
        throw new RuntimeException();
    }
    public void printList() {
        printList("");
    }
    public abstract void printList(String prefix);

    @Override
    public String toString() {
        return getName() + "(" + getSize() + ")";
    }
}

File.java

public class File extends Entry {
    private String name;
    private int size;

    public File(String name, int size) {
        this.name = name;
        this.size = size;
    }

    public String getName() {
        return this.name;
    }

    public int getSize() {
        return this.size;
    }

    public void printList(String prefix) {
        System.out.println(prefix + "/" + this);
    }
}

Directory.java

public class Directory extends Entry {
    private String name;
    private List<Entry> items = new ArrayList<Entry>();

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

    public String getName() {
        return this.name;
    }

    public int getSize() {
        int size = 0;
        Iterator it = this.items.iterator();
        while (it.hasNext()) {
            Entry entry = (Entry) it.next();
            size += entry.getSize();
        }
        return size;
    }

    public Entry add(Entry entry) {
        items.add(entry);
        return this;
    }

    public void printList(String prefix) {
        System.out.println(prefix + "/" + getName());
        Iterator it = items.iterator();
        while (it.hasNext()) {
            Entry entry = (Entry) it.next();
            entry.printList(prefix + "/" + this.name);
        }
    }
}

測(cè)試一下:

Client.java

public class Client {
    public static void main(String[] args) {
        Entry bindir = new Directory("bin");
        Entry usrdir = new Directory("usr");
        Entry tmpdir = new Directory("lib");

        bindir
                .add(new File("bash", 4))
                .add(new File("ls", 6))
                .add(new File("ip", 8));

        usrdir
                .add(new Directory("bin")
                    .add(new File("top", 10))
                    .add(new File("ssh", 12)))
                .add(new Directory("local")
                    .add(new Directory("bin")
                        .add(new File("eclipse", 4))
                        .add(new File("idea", 4)))
                    .add(new Directory("src")));

        tmpdir
                .add(new File("test.txt", 12));

        Entry rootdir = new Directory("root");
        rootdir.add(bindir).add(usrdir).add(tmpdir);
        rootdir.printList();
    }
}

輸出結(jié)果:

/root
/root/bin
/root/bin/bash(4)
/root/bin/ls(6)
/root/bin/ip(8)
/root/usr
/root/usr/bin
/root/usr/bin/top(10)
/root/usr/bin/ssh(12)
/root/usr/local
/root/usr/local/bin
/root/usr/local/bin/eclipse(4)
/root/usr/local/bin/idea(4)
/root/usr/local/src
/root/lib
/root/lib/test.txt(12)

總結(jié)

合成設(shè)計(jì)模式是一種辨識(shí)度比較高罗丰,應(yīng)用場(chǎng)景相對(duì)比較明確的設(shè)計(jì)模式,因此相對(duì)來說也比較好理解再姑。主要特征就兩條:

  1. 無論是“枝干“還是”葉子“萌抵,都是樹的“組成部分”,因此都有共同的抽象元镀,而“枝干”中的list成員變量引用的也是這個(gè)共同抽象的列表绍填。概括地說就是“整體”和“部分”具有一致性,是一種遞歸包含關(guān)系栖疑;
  2. 通常有一個(gè)“添加方法”讨永,類似于本例的add(),因?yàn)槭沁f歸操作遇革,一視同仁卿闹,這個(gè)方法通常定義在抽象類中,默認(rèn)拋出異常萝快,以便適用“葉子”節(jié)點(diǎn)無法添加子節(jié)點(diǎn)的情況锻霎。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市揪漩,隨后出現(xiàn)的幾起案子旋恼,更是在濱河造成了極大的恐慌,老刑警劉巖奄容,帶你破解...
    沈念sama閱讀 217,907評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蚌铜,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡嫩海,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門囚痴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來叁怪,“玉大人,你說我怎么就攤上這事深滚∞忍罚” “怎么了?”我有些...
    開封第一講書人閱讀 164,298評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵痴荐,是天一觀的道長(zhǎng)血柳。 經(jīng)常有香客問我,道長(zhǎng)生兆,這世上最難降的妖魔是什么难捌? 我笑而不...
    開封第一講書人閱讀 58,586評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上根吁,老公的妹妹穿的比我還像新娘员淫。我一直安慰自己,他們只是感情好击敌,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評(píng)論 6 392
  • 文/花漫 我一把揭開白布介返。 她就那樣靜靜地躺著,像睡著了一般沃斤。 火紅的嫁衣襯著肌膚如雪圣蝎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,488評(píng)論 1 302
  • 那天衡瓶,我揣著相機(jī)與錄音徘公,去河邊找鬼。 笑死鞍陨,一個(gè)胖子當(dāng)著我的面吹牛步淹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播诚撵,決...
    沈念sama閱讀 40,275評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼缭裆,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了寿烟?” 一聲冷哼從身側(cè)響起澈驼,我...
    開封第一講書人閱讀 39,176評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎筛武,沒想到半個(gè)月后缝其,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,619評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡徘六,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評(píng)論 3 336
  • 正文 我和宋清朗相戀三年内边,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片待锈。...
    茶點(diǎn)故事閱讀 39,932評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡漠其,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出竿音,到底是詐尸還是另有隱情和屎,我是刑警寧澤,帶...
    沈念sama閱讀 35,655評(píng)論 5 346
  • 正文 年R本政府宣布春瞬,位于F島的核電站柴信,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏宽气。R本人自食惡果不足惜随常,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評(píng)論 3 329
  • 文/蒙蒙 一潜沦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧线罕,春花似錦止潮、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至询件,卻和暖如春燃乍,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背宛琅。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工刻蟹, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人嘿辟。 一個(gè)月前我還...
    沈念sama閱讀 48,095評(píng)論 3 370
  • 正文 我出身青樓舆瘪,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親红伦。 傳聞我的和親對(duì)象是個(gè)殘疾皇子英古,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容