設計模式 —— 組合模式(Composite Pattern)

組合模式(Composite Pattern)

概念:

定義:組合模式 允許你將對象組合成樹型結構來表現“整體/部分”層次結構。組合能讓客戶以一致的方式處理個別對象以及對象組合。在大多數情況下,我們可以忽略對象組合和個別對象之間的差別。


在日常生活中我們經常會遇到樹型結構的問題,比如典型的公司管理,上司管理不同的下屬,下屬也可能屬於某個部門的上司。

組合模式

組合模式可以模糊簡單元素和複雜元素的概念,客戶程序可以向處理簡單元素一樣來處理複雜元素,從而使得客戶程序與複雜元素的內部結構解耦。


組成:

組合模式

Component(組合):爲組合中的所有對象定義一個接口。包括組合和葉節點。

Leaf(葉節點):葉節點通過實現了 Composite 支持的操作,定義了這內元素的行爲。

Composite(組件):定義組件的行爲,並且組件也擁有子節點。


例子:

公司僱員例子,CEO 有僱員,僱員中有部門經理,經理地面又有僱員。

組件類:
所有的組件都必須實現該接口,然而葉節點和組合節點的角色不同,所以有些方法可能並不適合某種節點。遇到這種情況時,有時候最好的方式是拋出運行時異常。

public abstract class EmployeeConponent {
    private String name;
    private String description;
    private double salary;

    //構造函數,包括姓名、描述、薪水
    public EmployeeConponent(String name, String description, double salary) {
        this.name = name;
        this.description = description;
        this.salary = salary;
    }

    //添加僱員
    public void add(EmployeeConponent employeeConponent) {
        throw new UnsupportedOperationException();
    }

    //刪除僱員
    public void remove(EmployeeConponent employeeConponent) {
        throw new UnsupportedOperationException();
    }

    //獲得某一個子節點
    public Object getChild(int i) {
        throw new UnsupportedOperationException();
    }

    public String getName() {
        return name;
    }

    public String getDescription() {
        return description;
    }

    public double getSalary() {
        return salary;
    }

    public void print() {
        System.out.print("name:" + name);
        System.out.print(" description:" + description);
        System.out.println(" salary:" + salary);
    }
}

Boss 類:

public class Boss extends EmployeeConponent {
    //僱員列表
    ArrayList<EmployeeConponent> subordinates;

    public Boss(String name, String description, double salary) {
        super(name, description, salary);
        subordinates = new ArrayList<EmployeeConponent>();
    }

    @Override
    public void add(EmployeeConponent employeeConponent) {
        subordinates.add(employeeConponent);
    }

    @Override
    public void remove(EmployeeConponent employeeConponent) {
        subordinates.remove(employeeConponent);
    }

    @Override
    public EmployeeConponent getChild(int i) {
        return (EmployeeConponent) subordinates.get(i);
    }

    //打印自己以及僱員
    @Override
    public void print() {
        System.out.print("name:" + super.getName());
        System.out.print(" description:" + super.getDescription());
        System.out.println(" salary:" + super.getSalary());
        for (EmployeeConponent i : subordinates) {
            i.print();
        }
        System.out.println();
    }
}

僱員類:

public class Employee extends EmployeeConponent {
    public Employee(String name, String description, double salary) {
        super(name, description, salary);
    }
}

測試類:

public class Client {
    public static void main(String[] args) {
        Boss CEO = new Boss("Li", "CEO", 25000);

        Employee employee1 = new Employee("Zhang", "Employee", 12000);
        Employee employee2 = new Employee("Zhao", "Employee", 12000);

        Boss manager = new Boss("Wang", "Manager", 20000);

        Employee employee3 = new Employee("He", "Employee", 12000);
        Employee employee4 = new Employee("Qi", "Empoyee", 12000);

        CEO.add(employee1);
        CEO.add(employee2);
        CEO.add(manager);
        manager.add(employee3);
        manager.add(employee4);

        CEO.print();
    }
}

組合模式


適用場景:

  • 當我們想表示對象的部分-整體層次結構(樹形結構,如文件系統、僱員關係等)。
  • 希望用戶忽略組合對象與單個對象的不同,用戶將統一地使用組合結構中的所有對象。
  • 組合模式解耦了客戶程序與複雜元素內部結構,從而使客戶程序可以向處理簡單元素一樣來處理複雜元素。
    如果你想要創建層次結構,並可以在其中以相同的方式對待所有元素,那麼組合模式就是最理想的選擇。

優缺點:

優點:

  • 高層模塊調用簡單,組合模式解耦了客戶程序與複雜元素內部結構。從而使客戶程序可以向處理簡單元素一樣來處理複雜元素。創建層次結構,並可以在其中以相同的方式對待所有元素。
  • 節點可以自由增加。

缺點:

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

依賴倒置原則:要依賴抽象,不要依賴具體類。

這個原則說明:不能讓高層組件依賴底層組件,而且,不管是高層組件或底層組件,都應該依賴於抽象。

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