設計模式(十二):組合模式


一、概述

  允許你將對象組合成樹形結構來表現“整體/部分”層次結構。組合能讓客戶以一致的方式處理個別對象以及組合對象。

二、解決問題

  組合模式解決這樣的問題,當我們的要處理的對象可以生成一顆樹形結構,而我們要對樹上的節點和葉子進行操作時,它能夠提供一致的方式,而不用考慮它是節點還是葉子。

 

三、結構類圖

四、應用實例

  上一講中,我們是以大學的院系結構來講解迭代器的,在組合模式中,我們還是引用這個例子。把學校作為根節點,學院做普通節點,專業就是葉子。

  首先,從上面的類圖中知道,對於客戶端來說,其需要面對的就是一個組件,而不用管是否節點還是葉子。我們就先來創建這樣一個組件

package com.jet.pattern.Composite;

/**
 * description:
 * 機構組件,學院和系稱為機構
 * Created by Administrator on 2016/11/17.
 */
public abstract class OrganizationComponent {
    // 每個方法提供默認的實現
    public void add(OrganizationComponent organizationComponent){
        throw new UnsupportedOperationException();
    }

    public void remove(OrganizationComponent organizationComponent){
        throw new UnsupportedOperationException();
    }

    public String getName(){
        throw new UnsupportedOperationException();
    }

    public String getDescription(){
        throw new UnsupportedOperationException();
    }

    public void print(){
        throw new UnsupportedOperationException();
    }

}

接着從上到下創建組件對象,創建學校對象

package com.jet.pattern.Composite.impl;

import com.jet.pattern.Composite.OrganizationComponent;

import java.util.ArrayList;
import java.util.List;

/**
 * description:
 * 大學對象
 * Created by Administrator on 2017/1/13.
 */
public class University extends OrganizationComponent {
    String name;
    String description;
    List<OrganizationComponent> organizationComponents = new ArrayList<OrganizationComponent>();

    public University(String name, String description) {
        this.name = name;
        this.description = description;
    }

    // 重寫機構組件的方法,其作為樹有增加和刪除方法
    @Override
    public void add(OrganizationComponent organizationComponent) {
        organizationComponents.add(organizationComponent);
    }

    @Override
    public void remove(OrganizationComponent organizationComponent) {
        organizationComponents.remove(organizationComponent);
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public String getDescription() {
        return description;
    }

    @Override
    public void print() {
        System.out.println("-------" + getName() + "-----------");
        // 大學下面有很多學院,把他們遍歷出來
        for(OrganizationComponent organizationComponent : organizationComponents){
            organizationComponent.print();
        }
    }
}

創建學院對象

package com.jet.pattern.Composite.impl;

import com.jet.pattern.Composite.OrganizationComponent;

import java.util.ArrayList;
import java.util.List;

/**
 * description:
 * 學院是一個機構,
 * Created by Administrator on 2017/1/13.
 */
public class College extends OrganizationComponent {
    String name;
    String description;
    List<OrganizationComponent> organizationComponents = new ArrayList<OrganizationComponent>();

    public College(String name, String description) {
        this.name = name;
        this.description = description;
    }

    // 重寫機構組件的方法,其作為樹有增加和刪除方法
    @Override
    public void add(OrganizationComponent organizationComponent) {
        organizationComponents.add(organizationComponent);
    }

    @Override
    public void remove(OrganizationComponent organizationComponent) {
        organizationComponents.remove(organizationComponent);
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public String getDescription() {
        return description;
    }

    @Override
    public void print() {
        System.out.println("-------" + getName() + "-----------");
        // 學院下面有很多專業,把他們遍歷出來
        for(OrganizationComponent organizationComponent : organizationComponents){
            organizationComponent.print();
        }
    }
}

創建專業(系)對象

package com.jet.pattern.Composite.impl;

import com.jet.pattern.Composite.OrganizationComponent;

/**
 * description:
 * 專業(系)對象
 * Created by Administrator on 2017/1/13.
 */
public class Department extends OrganizationComponent {
    String name;
    String description;

    public Department(String name, String description) {
        this.name = name;
        this.description = description;
    }

    // 重寫機構組件的方法,其作為葉子沒有增加和刪除方法
    @Override
    public String getName() {
        return name;
    }

    @Override
    public String getDescription() {
        return description;
    }

    // 葉子只需要輸出自己的信息
    @Override
    public void print() {
        System.out.println(getName());
    }
}

創建輸出對象,模擬客戶端

package com.jet.pattern.Composite.impl;

import com.jet.pattern.Composite.OrganizationComponent;

/**
 * description:
 * 輸出信息,模擬客戶調用
 * Created by Administrator on 2017/1/13.
 */
public class OutputInfo {
    OrganizationComponent allOrganization;

    public OutputInfo(OrganizationComponent allOrganization) {
        this.allOrganization = allOrganization;
    }

    public void printOrganization(){
        allOrganization.print();
    }
}

測試組合模式

package com.jet.pattern.Composite.test;

import com.jet.pattern.Composite.OrganizationComponent;
import com.jet.pattern.Composite.impl.College;
import com.jet.pattern.Composite.impl.Department;
import com.jet.pattern.Composite.impl.OutputInfo;
import com.jet.pattern.Composite.impl.University;

/**
 * description:
 * 測試組合模式
 * Created by Administrator on 2017/1/13.
 */
public class CompositeTest {
    public static void main(String[] args) {
        // 從大到小創建對象,學院和專業組合成為學校,先創建學校,它也是機構組件
        OrganizationComponent university = new University("清華大學","全國最好的大學");

        // 接着創建學院
        OrganizationComponent computerCollege = new College("計算機學院","計算機學院");
        OrganizationComponent infoEngineeringCollege = new College("信息工程學院","信息工程學院");

        // 計算機學院有下面專業
        computerCollege.add(new Department("計算機科學與技術","計算機科學與技術"));
        computerCollege.add(new Department("軟件工程 ","軟件工程"));
        computerCollege.add(new Department("網絡工程","網絡工程"));

        // 信息工程學院有下面專業
        infoEngineeringCollege.add(new Department("通信工程","通信工程"));
        infoEngineeringCollege.add(new Department("信息工程","信息工程"));

        // 學校有下面學院
        university.add(computerCollege);
        university.add(infoEngineeringCollege);

        // 輸出學校機構信息
        OutputInfo info = new OutputInfo(university);
        info.printOrganization();
    }
}

測試輸出結果如下:

五、使用場景

  1.當需要遍歷組織機構,或者處理的對象具有樹形結構時使用。

六、優缺點

  1.優點

  (1)、簡化客戶端操作。客戶端只需要面對一致的對象而不用考慮整體部分或者節點葉子的問題。

  (2)、具有較強的擴展性。當我們要更改組合對象時,我們只需要調整內部的層次關系,客戶端不用做出任何改動。

  (3)、方便創建出復雜的層次結構。客戶端不用理會組合里面的組成細節,容易添加節點或者葉子從而創建出復雜的樹形結構。

  2.缺點

  (1)、要求較高的抽象性,如果節點和葉子有很多差異性的話,比如很多方法和屬性都不一樣,難以實現組合模式。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM