設計模式(十)組合模式

版權聲明:轉載必須註明本文轉自曉_晨的博客:http://blog.csdn.net/niunai112

導航

設計模式之六大設計原則
設計模式(一)單例模式
設計模式(二)工廠模式
設計模式(三)策略模式
設計模式(四)適配器模式
設計模式(五)享元模式
設計模式(六)建造者模式
設計模式(七)原型模式
設計模式(八)橋接模式
設計模式(九)外觀模式
設計模式(十)組合模式
設計模式(十一)裝飾器模式
設計模式(十二)代理模式
設計模式(十三)迭代器模式
設計模式(十四)觀察者模式
設計模式(十五)中介者模式
設計模式(十六)命令模式
設計模式(十七)狀態模式
設計模式(十八)訪問者模式
設計模式(十九)責任鏈模式
設計模式(二十)解釋器模式
設計模式(二十一)備忘錄模式
設計模式(二十二)模板模式
設計模式總結篇(爲什麼要學習設計模式,學習設計模式的好處)

前言

組合模式是指將對象組合成樹形結構以表示“部分-整體”的層次結構,組合模式使得用戶對單個對象和組合對象的使用具有一致性。
其實可以想象成數據結構中的樹型結構一樣,他們有公有的方法和屬性,而特殊節點有自己特有的方法和屬性。

例子

LZ就構造一顆樹來說明這個問題,和樹不一樣的是,這個樹形結構包含兩種類型的節點,一個姑且叫一般節點【子,Leaf】,另一個叫不一般節點【父節點,Composite,(這裏的父節點與通常樹的父節點不同,只是說這個節點可以再包含子節點,而不是說這節點有子節點)】,不一般節點可以包含Component,而一般節點和不一般節點都是繼承Component。仔細看看這句話,這句話已經說完了組合模式的精髓,看不大懂就對着例子來看。

/***
 *
 *@Author ChenjunWang
 *@Description:公共的抽象類
 *@Date: Created in 21:27 2018/3/29
 *@Modified By:
 *
 */
public abstract class Component {
    int val;//所有節點都有值
    public abstract void add(Component component);
    public abstract void remove(Component component);

    public abstract void show();
    
}




/***
 *
 *@Author ChenjunWang
 *@Description:父節點類
 *@Date: Created in 21:36 2018/3/29
 *@Modified By:
 *
 */
public class Composite extends Component{
    List<Component> list = new ArrayList<>();//有一個列表來包涵它的子節點

    public Composite(int val){
        this.val = val;//構造函數
    }

    @Override
    public void add(Component component) {
        list.add(component);//往列表中加節點

    }

    @Override
    public void remove(Component component) {

        list.remove(component);//刪列表中的該節點
    }

    @Override
    public void show() {

        System.out.println(val);//若是父節點則輸出值並遍歷出她所有的子節點的值
        for (Component c : list){
            c.show();
        }

    }
}

/***
 *
 *@Author ChenjunWang
 *@Description:葉子節點類
 *@Date: Created in 21:35 2018/3/29
 *@Modified By:
 *
 */
public class Leaf extends Component{

    public Leaf(int val){
        this.val = val;//構造函數
    }

    @Override
    public void add(Component component) {
//因爲葉子節點不能添加,所有爲空
    }

    @Override
    public void remove(Component component) {
//不能刪除,爲空
    }

    @Override
    public void show() {

//輸出值
        System.out.println(val);
    }
}

/***
 *
 *@Author ChenjunWang
 *@Description:
 *@Date: Created in 21:42 2018/3/29
 *@Modified By:
 *
 */
public class Test {


    public static void main(String[] args) {
        Component composite1 = new Composite(1);
        Component composite2 = new Composite(12);
        Component composite3 = new Composite(23);
        Component leaf = new Leaf(34);
        composite1.add(composite2);
        composite2.add(composite3);
        composite3.add(leaf);
        System.out.println("從父節點1開始show");
        composite1.show();
        System.out.println("從父節點3開始show");
        composite3.show();

    }
}
輸出結果如下
---------------------------
從父節點1開始show
1
12
23
34
從父節點3開始show
23
34


UML圖
composite

上面就是一個組合模式的實際應用,我們會發現,有一個問題,那就是子節點也有add和remove方法,但是實際上,它應該是不允許訪問這方法的,不符合接口隔離原則。所以上面的爲不安全的組合模式。那如何做到安全呢,

/***
 *
 *@Author ChenjunWang
 *@Description:公共的抽象類
 *@Date: Created in 21:27 2018/3/29
 *@Modified By:
 *
 */
public abstract class Component {
    int val;//所有節點都有值

    public abstract void show();
    
}




/***
 *
 *@Author ChenjunWang
 *@Description:父節點類
 *@Date: Created in 21:36 2018/3/29
 *@Modified By:
 *
 */
public class Composite extends Component{
    List<Component> list = new ArrayList<>();//有一個列表來包涵它的子節點

    public Composite(int val){
        this.val = val;//構造函數
    }

    
    public void add(Component component) {
        list.add(component);//往列表中加節點

    }

  
    public void remove(Component component) {

        list.remove(component);//刪列表中的該節點
    }

    @Override
    public void show() {

        System.out.println(val);//若是父節點則輸出值並遍歷出她所有的子節點的值
        for (Component c : list){
            c.show();
        }

    }
}

/***
 *
 *@Author ChenjunWang
 *@Description:葉子節點類
 *@Date: Created in 21:35 2018/3/29
 *@Modified By:
 *
 */
public class Leaf extends Component{

    public Leaf(int val){
        this.val = val;//構造函數
    }

  
    @Override
    public void show() {

//輸出值
        System.out.println(val);
    }
}

/***
 *
 *@Author ChenjunWang
 *@Description:
 *@Date: Created in 21:42 2018/3/29
 *@Modified By:
 *
 */
public class Test {


    
    public static void main(String[] args) {
        Composite composite1 = new Composite(1);
        Composite composite2 = new Composite(12);
        Composite composite3 = new Composite(23);
        Component leaf = new Leaf(34);
        composite1.add(composite2);
        composite2.add(composite3);
        composite3.add(leaf);
        System.out.println("從父節點1開始show");
        composite1.show();
        System.out.println("從父節點3開始show");
        composite3.show();

    }
}
輸出結果如下
---------------------------
從父節點1開始show
1
12
23
34
從父節點3開始show
23
34

這樣就是安全組合模式了,子節點不再能調用到父節點的獨有的方法,但是對於調用的人來說,他在使用中,不再能已抽象類聲明瞭。

總結

優點

(1)組合模式使得客戶端代碼可以一致地處理對象和對象容器,無需關係處理的單個對象,還是組合的對象容器,將”客戶代碼與複雜的對象容器結構“解耦。
(2)更容易在組合體內加入對象部件. 客戶端不必因爲加入了新的對象部件而更改代碼。這一點符合開閉原則的要求,有利於系統的拓展和維護。

缺點

(1) 若使用安全的組合模式,得直接申明實現類,這在面向接口編程上是很不恰當的,與依賴倒置原則衝突。若使用不安全的組合模式,則違反接口隔離原則。
(2)使你的系統結構更加複雜。

Git地址

本篇實例Github地址:https://github.com/stackisok/Design-Pattern/tree/master/src/main/java/composite

回到最上方

有什麼不懂或者不對的地方,歡迎留言。
喜歡LZ文章的小夥伴們,可以關注一波,也可以留言,LZ會回你們的。
覺得寫得不錯的小夥伴,歡迎轉載,但請附上原文地址,謝謝_!

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