1. 程式人生 > 其它 >【設計模式從入門到精通】08-組合模式

【設計模式從入門到精通】08-組合模式

組合模式

筆記來源:尚矽谷Java設計模式(圖解+框架原始碼剖析)

目錄

組合模式

1、學校院系展示需求

編寫程式展示一個學校院系結構:

需求是這樣,要在一個頁面中展示出學校的院系組成,一個學校有多個學院,一個學院有多個系。如圖:

傳統方式解決學校院系展示(類圖)

問題分析

  • 1)將學院看做是學校的子類,系是學院的子類,這樣實際上是站在組織大小來進行分層次的
  • 2)實際上我們的要求是:在一個頁面中展示出學校的院系組成,一個學校有多個學院,一個學院有多個系。因此這種方案,不能很好實現的 管理
    的操作,比如對學院、系的新增、刪除、遍歷等
  • 3)解決方案:把學校、院、系都看做是組織結構,他們之間沒有繼承的關係,而是一個樹形結構,可以更好的實現管理操作 ==> 組合模式

2、組合模式基本介紹

  • 1)組合模式(Composite Pattern),又叫部分整體模式。它建立了物件組的樹形結構,將物件組合成樹狀結構以表示“整體-部分”的層次關係
  • 2)組合模式依據樹形結構來組合物件,用來表示部分以及整體層次
  • 3)這種型別的設計模式屬於結構型模式
  • 4)組合模式使得使用者對單個物件和組合物件的訪問具有一致性,即:組合能讓客戶以一致的方式處理個別對象以及組合物件

原理類圖

對原理結構圖的說明一即組合模式的角色及職責

  • 1)Component:這是組合中物件宣告介面。在適當情況下,實現所有類共有的介面預設行為,用於訪問和管理 Component子部件。Component可以是抽象類或者介面
  • 2)Leaf:在組合中表示葉子結點,葉子結點沒有子節點
  • 3)Composite:非葉子結點,用於儲存子部件,在Component介面中實現子部件的相關操作。比如增加、刪除

解決的問題

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

3、組合模式解決學校院系展示

UML 類圖

核心程式碼

// Component 抽象類
public abstract class OrganizationComponent {
    private String name;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

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

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

    public abstract void print();
}
// Composite 非葉子節點
public class University extends OrganizationComponent {
    List<organizationcomponent> organizationComponentList = new ArrayList<>();

    public University(String name) {
        super(name);
    }

    @Override
    public void add(OrganizationComponent organizationComponent) {
        organizationComponentList.add(organizationComponent);
    }

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

    @Override
    public void print() {
        for (OrganizationComponent organizationComponent : organizationComponentList) {
            organizationComponent.print();
        }
    }
}
public class College extends OrganizationComponent {
    List<organizationcomponent> organizationComponentList = new ArrayList<>();

    public College(String name) {
        super(name);
    }

    @Override
    public void add(OrganizationComponent organizationComponent) {
        organizationComponentList.add(organizationComponent);
    }

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

    @Override
    public void print() {
        System.out.println("=============" + getName() + "=============");
        for (OrganizationComponent organizationComponent : organizationComponentList) {
            organizationComponent.print();
        }
    }
}
// Leaf 葉子結點
public class Major extends OrganizationComponent {
    public Major(String name) {
        super(name);
    }

    @Override
    public void print() {
        System.out.println(getName());
    }
}
// 客戶端
public class Client {
    public static void main(String[] args) {
        //大學
        OrganizationComponent university = new University("清華大學");
        //學院
        OrganizationComponent computerCollege = new College("計算機學院");
        OrganizationComponent infoEngineerCollege = new College("資訊工程學院");
        //專業
        computerCollege.add(new Major("軟體工程"));
        computerCollege.add(new Major("網路工程"));
        computerCollege.add(new Major("電腦科學與技術"));
        infoEngineerCollege.add(new Major("通訊工程"));
        infoEngineerCollege.add(new Major("資訊工程"));

        university.add(computerCollege);
        university.add(infoEngineerCollege);
        university.print();
        //=============計算機學院=============
        //軟體工程
        //網路工程
        //電腦科學與技術
        //=============資訊工程學院=============
        //通訊工程
        //資訊工程
    }
}

4、JDK 原始碼分析

Java 的集合類—— HashMap 就使用了組合模式

UML 類圖

核心程式碼

// Component
public interface Map<k,v> {
    interface Entry<k,v> {}
}
public abstract class AbstractMap<k,v> implements Map<k,v> {}
// Composite
public class HashMap<k,v> extends AbstractMap<k,v> implements Map<k,v>, Cloneable, Serializable {
    // Leaf
    static class Node<k,v> implements Map.Entry<k,v> {}
}

說明

  • 1)Map 就是一個抽象的構建,類似Component
  • 2)HashMap 是一箇中間的構建,類似Composite,實現 / 繼承了相關方法 put、putAll
  • 3)Node 是 HashMap 的靜態內部類,類似Leaf葉子節點,這裡就沒有 put

5、注意事項和細節

  • 1)簡化客戶端操作:客戶端只需要面對一致的物件,而不用考慮整體部分或者節點葉子的問題
  • 2)具有較強擴充套件性:當我們要更改組合物件時,我們只需要調整內部的層次關係,客戶端不用做出任何改動
  • 3)方便建立複雜的層次結構:客戶端不用理會組合裡面的組成細節,容易新增節點或者葉子,從而創建出複雜的樹形結構
  • 4)需要遍歷組織機構,或者處理的物件具有樹形結構時,非常適合使用組合模式
  • 5)要求較高的抽象性,如果節點和葉子有很多差異性的話,比如很多方法和屬性都不一樣,不適合使用組合模式