一天一種設計模式之八-----組合模式

一.組合模式簡介

  1. 組合模式屬於結構型模式java

  2. 將組合模式合成樹形結構以表示「部分-總體」 的層次結構。「Composite」使得用戶對單個對象和組合對象的使用具備一致性。程序員

  3. 適用性:編程

    1. 你想表示對象的部分-總體層次結構。安全

    2. 你但願用戶忽略組合對象與單個對象的不一樣,用戶將統一地使用組合結構中的全部對象。ide

  4. 結構:測試

    1. Component 爲組合中的對象聲明接口。在適當狀況下,實現全部類共有接口的缺省行爲。聲明一個接口用於訪問和管理component的子組件。this

    2. leaf 在組合中表示葉節點對象,葉節點沒有子節點。spa

    3. composite 定義有子部件的那些不見的行爲。存儲子部件。在component接口中實現與子部件有關的操做。code

    4. client接口操做組合不見的對象。component

  5. 組合模式分爲透明模式和安全模式

    1. 透明模式:在Component中聲明全部用來管 理子對象的方法,如Add()方法,Remove()方法及GetChild()方法,全部實現Component接口的子類都具有這些方法,這使得 Component和子類具有一致的行爲接口,使得對客戶端無需區別樹葉和樹枝對象。

    2. 安全模式: 在透明模式基礎上把Component中聲明全部用來管理子對象的方法移到Composite中,在Composite實現子對象的管理方法,那麼 Leaf就沒有子對象管理方法,這使得Composite和Leaf的行爲接口不一致,因此客戶端在調用時要知道樹葉和樹枝對象存在。

  6. 組合模式符合開放封閉原則,迪米特法則。

  7. 組合模式優勢

    1. 高層模塊調用簡單:一棵屬性結構中全部節點都是component,局部和總體對調用者來講沒有任何區別,也就是說,高層模塊沒必要關心本身處理的是單個對象仍是整個組合結構,簡化了高層模塊的代碼。

    2. 節點自由增長:使用組合模式後,若是想增長一個樹枝節點,樹葉節點,只要找到它的父節點set進去就能夠。對之後維護很是簡單。

  8. 組合模式缺點

    1. 樹枝和樹葉的實現中直接使用了實現類,這在面向接口編程上是很不恰當的,與依賴倒置原則衝突。

    2. 經過繼承來實現的結構型模式,必定要當心子類覆蓋父類方法,由於這樣可能致使整個結構的功能發生難以預知的變化。

  9. 應用場景:

    1. 維護一個樹形菜單,文件系統等。

二.測試代碼

1.下述代碼是一種透明模式的組合模式

public class ZuhemoshiTest {
    public static void main(String[] args) {
        Employer employer=new ProjectManager("項目經理");
        Employer employer2=new Programer("程序員1");
        Employer employer3=new Programer("程序員2");
        employer.add(employer2);
        employer.add(employer3);
    }
}
abstract class Employer{
    private String name;
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public abstract void add(Employer employer);
    public abstract void delete(Employer employer);
    public List<Employer> employers;
    public void printInfo(){
        System.out.println(name);
    }
    public List<Employer> getEmployers(){
        return employers;
    }
    public  void displayTree(Employer root) {//遞歸遍歷整個樹。
        List<Employer> children = root.getEmployers();

        for (Employer employer : children) {
            System.out.println(employer.getName());
            if(employer.getEmployers()!=null){
                for(Employer employer2:employer.getEmployers()){
                    displayTree(employer2);
                }
            }
        }
    }
}
class Programer extends Employer{//至關於leaf
    public Programer(String name){
        setName(name);
        employers=null;//最低端的程序員,能僱傭的只有腦子T T
    }
    @Override
    public void add(Employer employer) {
    }

    @Override
    public void delete(Employer employer) {
    }
    
}
class ProjectManager extends Employer{
    public ProjectManager(String name){
        setName(name);
        employers=new ArrayList<Employer>();
    }
    
    @Override
    public void add(Employer employer) {
        employers.add(employer);
    }

    @Override
    public void delete(Employer employer) {
        employers.remove(employer);
    }
    
}

上述代碼定義了一個樹形結構,假如咱們想定義一個employer的動做,只須要在父類中定義,所有子類重寫或者直接繼承便可。

2.安全模式測試代碼

public class ZuhemoshiTest {
    public static void main(String[] args) {
        Manager manager=new ProjectManager("項目經理");
        Employer employer2=new Programer("程序員1");
        Employer employer3=new Programer("程序員2");
        manager.add(employer2);
        manager.add(employer3);
    }
}
class Employer{
    protected String name;
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
}
class Programer extends Employer{//至關於leaf
    public Programer(String name){
        setName(name);
    }    
}
abstract class Manager extends Employer{
    public abstract void add(Employer employer);
    public abstract void delete(Employer employer);
    public List<Employer> employers;
    public void printInfo(){
        System.out.println(name);
    }
    public List<Employer> getEmployers(){
        return employers;
    }
    public  void displayTree(Manager root) {
        List<Employer> children = root.getEmployers();

        for (Employer employer : children) {
            if(employer instanceof Manager){
                System.out.println(employer.getName());
                displayTree((Manager)employer);
            }else {
                System.out.println(employer.getName());
            }
        }
    }
}
class ProjectManager extends Manager{
    public ProjectManager(String name){
        setName(name);
        employers=new ArrayList<Employer>();
    }
    
    @Override
    public void add(Employer employer) {
        employers.add(employer);
    }

    @Override
    public void delete(Employer employer) {
        employers.remove(employer);
    }
    
}

3.爲了應對組合模式沒有實現面向接口編程,我的認爲能夠經過接口實現。核心代碼以下,這個相關資料裏沒有提到過,不知道對不對。歡迎大神指正。

interface Employ{
    public List<Employ> employs=new ArrayList<Employ>();//接口中聲明的變量是final的,表示變量地址不會改變
    void add(Employ employ);
    void remove(Employ employ);
}
相關文章
相關標籤/搜索