13-設計模式-組合模式

組合模式概念

以下摘自菜鳥教程

意圖:將對象組合成樹形結構以表示”部分-整體”的層次結構。組合模式使得用戶對單個對象和組合對象的使用具有一致性。

主要解決:它在我們樹型結構的問題中,模糊了簡單元素和複雜元素的概念,客戶程序可以向處理簡單元素一樣來處理複雜元素,從而使得客戶程序與複雜元素的內部結構解耦。

何時使用:
1、您想表示對象的部分-整體層次結構(樹形結構)。
2、您希望用戶忽略組合對象與單個對象的不同,用戶將統一地使用組合結構中的所有對象。

如何解決:樹枝和葉子實現統一接口,樹枝內部組合該接口。

關鍵代碼:樹枝內部組合該接口,並且含有內部屬性 List,裏面放 Component。

應用實例:
1、算術表達式包括操作數、操作符和另一個操作數,其中,另一個操作符也可以是操作數、操作符和另一個操作數。
2、在 JAVA AWT 和 SWING 中,對於 Button 和 Checkbox 是樹葉,Container 是樹枝。

優點:
1、高層模塊調用簡單。
2、節點自由增加。

缺點:在使用組合模式時,其葉子和樹枝的聲明都是實現類,而不是接口,違反了依賴倒置原則。

使用場景:部分、整體場景,如樹形菜單,文件、文件夾的管理。

注意事項:定義時爲具體類。

組合模式主要突出兩個關鍵字:樹形結構、整體-部分
接下來先看一個案例

案例

已知,電腦中文件與文件夾。父文件夾中可以存在子文件和子文件夾,子文件夾中又可以存在其子文件夾的子文件和子文件夾。

Component(抽象構件)

可以是接口或抽象類,爲葉子構件和容器構件對象聲明接口,在該角色中可以包含所有子類共有行爲的聲明和實現。在抽象構件中定義了訪問及管理它的子構件的方法,如增加子構件、刪除子構件、獲取子構件等。

public interface Component {

    /**
     * 添加組件
     * @return void
     * @param component
     * 時間:2018年4月27日
     */
    void add(Component component); 

    /**
     * 移除組件
     * @return void
     * @param component
     * 時間:2018年4月27日
     */
    void remove(Component component);

    /**
     * 獲取組件
     * @return Component
     * @param i
     * @return
     * 時間:2018年4月27日
     */
    Component getCom(int i);

    /**
     * 需要執行的方法
     * @return void
     * 時間:2018年4月27日
     */
    void operation();

}

Leaf(葉子構件)

在組合結構中表示葉子節點對象,葉子節點沒有子節點,它實現了在抽象構件中定義的行爲。對於那些訪問及管理子構件的方法,可以通過異常等方式進行處理。

public class CFile implements Component{

    private String name; 

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

    @Override
    public void add(Component component) {
        System.out.println("error");
    }

    @Override
    public void remove(Component component) {
        System.out.println("error");
    }

    @Override
    public Component getCom(int i) {
        System.out.println("error");
        return null;
    }

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

}

Composite(容器構件)

在組合結構中表示容器節點對象,容器節點包含子節點,其子節點可以是葉子節點,也可以是容器節點,它提供一個集合用於存儲子節點,實現了在抽象構件中定義的行爲,包括那些訪問及管理子構件的方法,在其業務方法中可以遞歸調用其子節點的業務方法。

public class CFolder implements Component{

    private String name;

    private List<Component> list;

    public CFolder(String name) {
        this.name = name;
        list = new ArrayList<>();
    }

    @Override
    public void add(Component component) {
        list.add(component);
    }

    @Override
    public void remove(Component component) {
        list.remove(component);
    }

    @Override
    public Component getCom(int i) {
        return list.get(i);
    }

    @Override
    public void operation() {
        System.out.println(name);
        System.out.println("打開了:" + name);
        for (Component component : list) {
            component.operation();
        }
    }
}

測試類

public class Test {
    public static void main(String[] args) {
        Component component1 = new CFile("A");
        Component component2 = new CFile("B");
        Component component3 = new CFile("C");
        Component component4 = new CFile("D");
        Component component5 = new CFolder("1");
        Component component6 = new CFolder("2");
        Component component7 = new CFolder("3");

        component5.add(component1);
        component5.add(component2);
        component5.add(component6);

        component6.add(component3);
        component6.add(component7);

        component7.add(component4);

        component5.operation();
    }
}

本文參考

https://www.cnblogs.com/lfxiao/p/6816026.html

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