天天看點

Java設計模式 - 組合模式

簡介

組合模式(Composite Pattern),又叫部分整體模式,是用于把一組相似的對象當作一個單一的對象。組合模式依據樹形結構來組合對象,用來表示部分以及整體層次。這種類型的設計模式屬于結構型模式,它建立了對象組的樹形結構。

組合模式原理

首先先看一下組合的UML圖

Java設計模式 - 組合模式

Compoent:抽象類或者接口,是組合對象聲明的接口,實作所有類的預設行為,用于通路、管理子部件。

Leaf:組合中的葉子節點,最小的類

Composite:非葉子節點,用來操作組合對象,存儲子部件。

組合模式執行個體

接下來用一個例子來學習組合模式,學校有學院,學院下有專業,這就是一層一層的關系,需要在一個頁面中展現出那個學校有什麼學院,學院下有什麼專業。

來看一下例子的類圖

Java設計模式 - 組合模式

①、定義抽象類-Component

定義屬性,構造器,getset,操作方法需要預設實作,因為在葉子節點是不需要去實作的,如果定義成抽象類,子類就必須實作了。在定義一個抽象類-列印資訊。

package com.lyd.demo.composite;

/**
 * @Author: lyd
 * @Description: 抽象類
 * @Date: 2022-08-30
 */
public abstract class OrganizationComponent {
    private String name;
    private String description;
    public OrganizationComponent(String name, String description) {
        this.name = name;
        this.description = description;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    // 添加 - 子類不一定需要實作
    public void add(OrganizationComponent organizationComponent) {
        throw new UnsupportedOperationException();
    }
    // 删除 - 子類不一定需要實作
    public void remove(OrganizationComponent organizationComponent) {
        throw new UnsupportedOperationException();
    }
    // 列印 - 子類必須去實作
    public abstract void print();
}      

②、定義葉子類和非葉子類

大學類:非葉子,組合 院系類;定義一個數組來存放組合對象,通過重寫操作方法對其進行操作。

package com.lyd.demo.compose;
import com.lyd.demo.composite.OrganizationComponent;
import java.util.ArrayList;
import java.util.List;
/**
 * @Author: lyd
 * @Description: 學校類 - 繼承OrganizationComponent - 組合 院系類
 * @Date: 2022-08-30
 */
public class University extends OrganizationComponent {
    // 組合 College 類
    List<OrganizationComponent> organizationComponents = new ArrayList<OrganizationComponent>();
    public University(String name, String description) {
        super(name, description);
    }
    /**
     * 重寫add
     */
    @Override
    public void add(OrganizationComponent organizationComponent) {
        organizationComponents.add(organizationComponent);
    }
    /**
     * 重寫remove
     */
    @Override
    public void remove(OrganizationComponent organizationComponent) {
        organizationComponents.add(organizationComponent);
    }
    @Override
    public String getName() {
        return super.getName();
    }
    @Override
    public String getDescription() {
        return super.getDescription();
    }
    // 列印包含學院的資訊
    @Override
    public void print() {
        System.out.println("< " + getName() + " >");
        // 将所有學院資訊列印出來
        for (OrganizationComponent o : organizationComponents) {
            o.print();
        }
    }
}      

學院類:非葉子,組合Department類,定義一個數組來存放組合對象,通過重寫操作方法對其進行操作。

package com.lyd.demo.compose;
import com.lyd.demo.composite.OrganizationComponent;
import java.util.ArrayList;
import java.util.List;
/**
 * @Author: lyd
 * @Description: 學院類
 * @Date: 2022-08-30
 */
public class College extends OrganizationComponent {
    // 組合 Department 類
    List<OrganizationComponent> organizationComponents = new ArrayList<OrganizationComponent>();
    public College(String name, String description) {
        super(name, description);
    }
    /**
     * 重寫add
     */
    @Override
    public void add(OrganizationComponent organizationComponent) {
        organizationComponents.add(organizationComponent);
    }
    /**
     * 重寫remove
     */
    @Override
    public void remove(OrganizationComponent organizationComponent) {
        organizationComponents.add(organizationComponent);
    }
    @Override
    public String getName() {
        return super.getName();
    }
    @Override
    public String getDescription() {
        return super.getDescription();
    }
    // 列印包含學院的資訊
    @Override
    public void print() {
        System.out.println("< " + getName() + " >");
        // 将所有專業資訊列印出來
        for (OrganizationComponent o : organizationComponents) {
            o.print();
        }
    }
}      

專業類:葉子節點,沒有組合的集合,是以不需要進行操作,隻需要進行輸出列印。

package com.lyd.demo.compose;
import com.lyd.demo.composite.OrganizationComponent;
/**
 * @Author: lyd
 * @Description: 專業類
 * @Date: 2022-08-30
 */
public class Department extends OrganizationComponent {
    // 已經沒有集合了
    public Department(String name, String description) {
        super(name, description);
    }
    @Override
    public String getName() {
        return super.getName();
    }
    @Override
    public String getDescription() {
        return super.getDescription();
    }
    // 葉子節點,就不需要add和remove
    @Override
    public void print() {
        System.out.println(getName());
    }
}      

③、測試

package com.lyd.demo.test;
import com.lyd.demo.compose.College;
import com.lyd.demo.compose.Department;
import com.lyd.demo.compose.University;
import com.lyd.demo.composite.OrganizationComponent;
/**
 * @Author: lyd
 * @Description: 測試
 * @Date: 2022-08-30
 */
public class ComposeTest {
    public static void main(String[] args) {
        // 建立大學
        OrganizationComponent ZheJiangUniversity = new University("浙江大學", "人才之地");
        // 建立學院
        OrganizationComponent ComputerCollege = new College("計算機科學與技術學院", "-->計算機科學與技術學院");
        OrganizationComponent OpticalCollege = new College("光電科學與工程學院", "-->光電科學與工程學院");
        // 建立專業
        Department ComputerDepartment = new Department("計算機科學與技術", "--計算機科學與技術");
        Department SoftWareDepartment = new Department("軟體工程", "--軟體工程");
        Department OpticalDepartment = new Department("光電資訊科學與工程", "--光電資訊科學與工程");
        // 添加專業
        ComputerCollege.add(ComputerDepartment);
        ComputerCollege.add(SoftWareDepartment);
        OpticalCollege.add(OpticalDepartment);
        // 添加學院
        ZheJiangUniversity.add(ComputerCollege);
        ZheJiangUniversity.add(OpticalCollege);
        // 列印所有
        ZheJiangUniversity.print();
        System.out.println("*******************************");
        // 列印學院
        ComputerCollege.print();
        System.out.println("*******************************");
        // 列印院系
        ComputerDepartment.print();
    }
}      

組合可以了解成是層層相套。