20巩踏、Android設(shè)計(jì)模式---(物以類聚)組合模式

一、介紹续搀,定義

將對(duì)象組合呈樹形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu)蛀缝,使得用戶對(duì)單個(gè)對(duì)象和組合對(duì)象的使用具有一致性。
比如目代,總公司下設(shè)總公司行政部、總公司研發(fā)部和子公司嗤练,而子公司又下設(shè)子公司行政部和子公司研發(fā)部榛了。

二、使用場(chǎng)景

(1)表示對(duì)象的部分-整體層次結(jié)構(gòu)時(shí)煞抬;
(2)從一個(gè)整體中能夠獨(dú)立出部分模塊或功能的場(chǎng)景霜大。

三、UML類圖

25.png

角色說明:
Component(抽象組件角色):定義參加組合對(duì)象的共有方法和屬性革答,可以定義一些默認(rèn)的函數(shù)或?qū)傩浴?br> Leaf(葉子節(jié)點(diǎn)):葉子沒有子節(jié)點(diǎn)战坤,因此是組合樹的最小構(gòu)建單元曙强。
Composite(樹枝節(jié)點(diǎn)):定義所有枝干節(jié)點(diǎn)的行為,存儲(chǔ)子節(jié)點(diǎn)途茫,實(shí)現(xiàn)相關(guān)操作碟嘴。

四、通用代碼

1囊卜、安全的組合模式
抽象根節(jié)點(diǎn):為組合中的對(duì)象聲明接口

public abstract class Component {
    // 節(jié)點(diǎn)名
    protected String name;
    public Component(String name) {
        this.name = name;
    }
    / /具體的邏輯方法由子類實(shí)現(xiàn)
    public abstract void doSomething();
}

具體枝干節(jié)點(diǎn):定義有子節(jié)點(diǎn)的那些枝干節(jié)點(diǎn)的行為娜扇,存儲(chǔ)子節(jié)點(diǎn)

public class Composite extends Component {
    //存儲(chǔ)節(jié)點(diǎn)的容器
    private List<Component> components = new ArrayList<>();

    public Composite(String name) {
        super(name);
    }

    @Override
    public void doSomething() {
        System.out.println(name);
        if (components != null) {
            for (Component component : components) {
                component.doSomething();
            }
        }
    }

    /**
     * 添加子節(jié)點(diǎn)
     * @param child 子節(jié)點(diǎn)
     */
    public void addChild(Component child) {
        components.add(child);
    }

    /**
     * 移除子節(jié)點(diǎn)
     * @param child 子節(jié)點(diǎn)
     */
    public void removeChild(Component child) {
        components.remove(child);
    }

    /**
     * 獲取子節(jié)點(diǎn)
     * @param index子節(jié)點(diǎn)對(duì)應(yīng)下標(biāo)
     * @return 子節(jié)點(diǎn)
     */
    public Component getChildren(int index) {
        return components.get(index);
    }
}

具體葉子節(jié)點(diǎn):葉子節(jié)點(diǎn)沒有子節(jié)點(diǎn),在組合中定義節(jié)點(diǎn)對(duì)象的行為

public class Leaf extends Component{

    public Leaf(String name) {
        super(name);
    }

    @Override
    public void doSomething() {
        System.out.println(name);
    }
}

客戶類:通過Component接口操縱組合節(jié)點(diǎn)的對(duì)象

public class Client {
    public static void main(String[] args) {
        // 構(gòu)造一個(gè)根節(jié)點(diǎn)
        Composite root = new Composite("Root");

        // 構(gòu)造兩個(gè)枝干節(jié)點(diǎn)
        Composite branch1 = new Composite("Branch1");
        Composite branch2 = new Composite("Branch2");

        // 構(gòu)造兩個(gè)葉子節(jié)點(diǎn)
        Leaf leaf1 = new Leaf("Leaf1");
        Leaf leaf2 = new Leaf("Leaf2");

        // 將葉子節(jié)點(diǎn)添加至枝干節(jié)點(diǎn)中
        branch1.addChild(leaf1);
        branch2.addChild(leaf2);

        // 將枝干節(jié)點(diǎn)添加至根節(jié)點(diǎn)中
        root.addChild(branch1);
        root.addChild(branch2);

        // 執(zhí)行方法
        root.doSomething();
    }
}

結(jié)果:

26.png

這里有一個(gè)很大的弊端栅组,我們?cè)诳蛻纛愔兄苯邮褂昧薈omponent的實(shí)現(xiàn)類雀瓢,這與依賴倒置原則(高層次的模塊不依賴于低層次的模塊的實(shí)現(xiàn)細(xì)節(jié)的目的)相違背。
我們將位于Composite的一些方法定義到Component中

2透明的組合模式抽象根節(jié)點(diǎn):為組合中的對(duì)象聲明接口

public abstract class Component {
    // 節(jié)點(diǎn)名
    protected String name;

    public Component(String name) {
        this.name = name;
    }
    /**
     * 具體的邏輯方法由子類實(shí)現(xiàn)
     */
    public abstract void doSomething();

    /**
     * 添加子節(jié)點(diǎn)
     * @param child子節(jié)點(diǎn)
     */
    public abstract void addChild(Component child);

    /**
     * 移除子節(jié)點(diǎn)
     * @param child子節(jié)點(diǎn)
     */
    public abstract void removeChild(Component child);

    /**
     * 獲取子節(jié)點(diǎn)
     * @param index子節(jié)點(diǎn)對(duì)應(yīng)下標(biāo)
     * @return 子節(jié)點(diǎn)
     */
    public abstract Component getChildren(int index);
}

透明的組合模式具體枝干節(jié)點(diǎn):定義有子節(jié)點(diǎn)的那些枝干節(jié)點(diǎn)的行為玉掸,存儲(chǔ)子節(jié)點(diǎn)

public class Composite extends Component {
    /*
     * 存儲(chǔ)節(jié)點(diǎn)的容器
     */
    private List<Component> components = new ArrayList<>();

    public Composite(String name) {
        super(name);
    }

    @Override
    public void doSomething() {
        System.out.println(name);
        if (components != null) {
            for (Component component : components) {
                component.doSomething();
            }
        }
    }

    @Override
    public void addChild(Component child) {
        components.add(child);
    }

    @Override
    public void removeChild(Component child) {
        components.remove(child);
    }

    @Override
    public Component getChildren(int index) {
        return components.get(index);
    }
}

透明的組合模式具體葉子節(jié)點(diǎn):葉子節(jié)點(diǎn)沒有子節(jié)點(diǎn)刃麸,在組合中定義節(jié)點(diǎn)對(duì)象的行為

public class Leaf extends Component {

    public Leaf(String name) {
        super(name);
    }

    @Override
    public void doSomething() {
        System.out.println(name);
    }

    @Override
    public void addChild(Component child) {
        throw new UnsupportedOperationException("葉子節(jié)點(diǎn)沒有子節(jié)點(diǎn)");
    }

    @Override
    public void removeChild(Component child) {
        throw new UnsupportedOperationException("葉子節(jié)點(diǎn)沒有子節(jié)點(diǎn)");
    }

    @Override
    public Component getChildren(int index) {
        throw new UnsupportedOperationException("葉子節(jié)點(diǎn)沒有子節(jié)點(diǎn)");
    }
}

透明的組合模式客戶類:通過Component接口操縱組合節(jié)點(diǎn)的對(duì)象

public class Client {
    public static void main(String[] args) {
        // 構(gòu)造一個(gè)根節(jié)點(diǎn)
        Component root = new Composite("Root");

        // 構(gòu)造兩個(gè)枝干節(jié)點(diǎn)
        Component branch1 = new Composite("Branch1");
        Component branch2 = new Composite("Branch2");

        // 構(gòu)造兩個(gè)葉子節(jié)點(diǎn)
        Component leaf1 = new Leaf("Leaf1");
        Component leaf2 = new Leaf("Leaf2");

        // 將葉子節(jié)點(diǎn)添加至枝干節(jié)點(diǎn)中
        branch1.addChild(leaf1);
        branch2.addChild(leaf2);

        // 將枝干節(jié)點(diǎn)添加至根節(jié)點(diǎn)中
        root.addChild(branch1);
        root.addChild(branch2);

        // 執(zhí)行方法
        root.doSomething();
    }
}

五、簡(jiǎn)單實(shí)現(xiàn)

文件和文件夾

六司浪、模式的優(yōu)缺點(diǎn):

組合模式在Android中最經(jīng)典的實(shí)現(xiàn)就是View和ViewGrounp的嵌套組合泊业。當(dāng)然這種模式真正需要開發(fā)者去實(shí)現(xiàn)的并不多。
優(yōu)點(diǎn):
(1)可以清楚的定義分層次的復(fù)雜對(duì)象断傲,表示對(duì)象的全部或部分層次脱吱,它讓高層模塊忽略了層次的差異,方便對(duì)整個(gè)層次結(jié)構(gòu)進(jìn)行控制认罩;
(2)高層模塊可以一致的使用一個(gè)組合結(jié)構(gòu)或其中單個(gè)對(duì)象箱蝠,不必關(guān)心處理的是單個(gè)對(duì)象還是整個(gè)組合結(jié)構(gòu),簡(jiǎn)化了高層模塊的代碼垦垂;
(3)在組合模式中增加新的枝干構(gòu)件和葉子構(gòu)件都很方便宦搬,無須對(duì)現(xiàn)有類庫(kù)進(jìn)行任何修改,符合“開閉原則”劫拗;
(4)組合模式為樹形結(jié)構(gòu)的面向?qū)ο髮?shí)現(xiàn)提供了一種靈活的解決方案间校,通過葉子對(duì)象和枝干對(duì)象的遞歸組合,可以形成復(fù)雜的樹形結(jié)構(gòu)页慷,但對(duì)樹形結(jié)構(gòu)的控制卻非常簡(jiǎn)單憔足。
缺點(diǎn):
在新增構(gòu)件時(shí)不好對(duì)枝干中的構(gòu)件類型進(jìn)行限制,不能依賴類型系統(tǒng)來施加這些約束酒繁,因?yàn)樵诖蠖鄶?shù)情況下滓彰,它們都來自于相同的抽象層,此時(shí)州袒,必須及時(shí)進(jìn)行類型檢查來實(shí)現(xiàn)揭绑,這個(gè)實(shí)現(xiàn)過程較為復(fù)雜。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末郎哭,一起剝皮案震驚了整個(gè)濱河市他匪,隨后出現(xiàn)的幾起案子菇存,更是在濱河造成了極大的恐慌,老刑警劉巖邦蜜,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件依鸥,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡畦徘,警方通過查閱死者的電腦和手機(jī)毕籽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來井辆,“玉大人关筒,你說我怎么就攤上這事”保” “怎么了蒸播?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)萍肆。 經(jīng)常有香客問我袍榆,道長(zhǎng),這世上最難降的妖魔是什么塘揣? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任包雀,我火速辦了婚禮,結(jié)果婚禮上亲铡,老公的妹妹穿的比我還像新娘才写。我一直安慰自己,他們只是感情好奖蔓,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布赞草。 她就那樣靜靜地躺著,像睡著了一般吆鹤。 火紅的嫁衣襯著肌膚如雪厨疙。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天疑务,我揣著相機(jī)與錄音沾凄,去河邊找鬼。 笑死知允,一個(gè)胖子當(dāng)著我的面吹牛搭独,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播廊镜,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼唉俗!你這毒婦竟也來了嗤朴?” 一聲冷哼從身側(cè)響起配椭,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎雹姊,沒想到半個(gè)月后股缸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吱雏,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年敦姻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片歧杏。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡镰惦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出犬绒,到底是詐尸還是另有隱情旺入,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布凯力,位于F島的核電站茵瘾,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏咐鹤。R本人自食惡果不足惜拗秘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望祈惶。 院中可真熱鬧雕旨,春花似錦、人聲如沸行瑞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)血久。三九已至突照,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間氧吐,已是汗流浹背讹蘑。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留筑舅,地道東北人座慰。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像翠拣,于是被迫代替她去往敵國(guó)和親版仔。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

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