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

1、組合模式的定義與特點

在這裏插入圖片描述

1.1、組合模式的定義

組合模式,又叫作部分-整體 模式,它是一種將對象組合成樹狀的層次結構的模式,用來表示 “部分-整體” 的關係,使用戶對單個對、象和組合對象具有一致的訪問性。

1.2、解決的問題

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

在這裏插入圖片描述

1.3、優點:

  1. 組合模式使得客戶端代碼可以一致地處理單個對象和組合對象,無須關心自己處理的是單個對象,還是組合對象,這簡化了客戶端代碼;
  2. 更容易在組合體內加入新的對象,客戶端不會因爲加入了新的對象而更改源代碼,滿足“開閉原則”;

1.4、缺點:

  1. 設計較複雜,客戶端需要花更多時間理清類之間的層次關係;
  2. 不容易限制容器中的構件;
  3. 不容易用繼承的方法來增加構件的新功能;

2、組合模式的UML圖

在這裏插入圖片描述

組合模式包含以下主要角色。

  1. Component(抽象構件):定義 LeafComposite 的公共接口,並實現它們的默認行爲。

    透明組合模式 中,Component 還聲明訪問和管理子類的接口;

    安全組合模式 中,不會聲明訪問和管理子類的接口,而管理工作由 Composite 構件 完成。

  2. Leaf(樹葉):葉節點對象,它沒有子節點,用於實現 Component 中聲明的公共接口。

  3. Composite(樹枝):分支節點對象,它有子節點。它實現 Component 中聲明的接口,它的主要作用是存儲和管理子部件,通常包含 add()remove()getChild() 等方法。

3、組合模式在學校院系展示的應用實例

3.1、分析:

一個學校院系結構:一個學校有多個學院,一個學院有多個系。
在這裏插入圖片描述

需求是在一個頁面中展示出學校的院系組成。
在這裏插入圖片描述

3.2、代碼

Component(抽像)

/**
 * 抽像組件
 */
public abstract class Component {

	/**名字*/
	private String name;
	/**說明*/
	private String des;
	
	protected  void add(Component organizationComponent) {
		//默認實現
		throw new UnsupportedOperationException();
	}
	
	protected  void remove(Component organizationComponent) {
		//默認實現
		throw new UnsupportedOperationException();
	}

	//構造器
	public Component(String name, String des) {
		super();
		this.name = name;
		this.des = des;
	}

	public String getName() {
		return name;
	}

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

	public String getDes() {
		return des;
	}

	public void setDes(String des) {
		this.des = des;
	}
	
	//方法print, 做成抽象的, 子類都需要實現 
	protected abstract void print();	
}

Composite: University(大學)


/**
 * University ,大學。
 * 是 Composite , 可以管理College
 */
public class University extends Component {

	List<Component> componentList = new ArrayList<Component>();

	// 構造器
	public University(String name, String des) {
		super(name, des);
	}

	// 重寫add
	@Override
	protected void add(Component component) {
		componentList.add(component);
	}

	// 重寫remove
	@Override
	protected void remove(Component component) {
		componentList.remove(component);
	}

	@Override
	public String getName() {
		return super.getName();
	}

	@Override
	public String getDes() {
		return super.getDes();
	}

	// print方法,就是輸出University 包含的學院
	@Override
	protected void print() {
		System.out.println("--------------" + getName() + "--------------");
		//遍歷 componentList 
		for (Component component : componentList) {
			component.print();
		}
	}

}

Composite:College(學院)

/**
 * 學院
 */
public class College extends Component {

	//List 中 存放的Department
	List<Component> componentList = new ArrayList<Component>();

	// 構造器
	public College(String name, String des) {
		super(name, des);
	}

	// 重寫add
	@Override
	protected void add(Component component) {
		//  將來實際業務中,Colleage 的 add 和  University add 不一定完全一樣
		componentList.add(component);
	}

	// 重寫remove
	@Override
	protected void remove(Component component) {
		componentList.remove(component);
	}

	@Override
	public String getName() {
		return super.getName();
	}

	@Override
	public String getDes() {
		return super.getDes();
	}

	// print方法,就是輸出University 包含的學院
	@Override
	protected void print() {
		System.out.println("--------------" + getName() + "--------------");
		//遍歷 componentList 
		for (Component component : componentList) {
			component.print();
		}
	}
}

Leaf:Department (系)

/**
 * 系,專業
 */
public class Department extends Component {

	//沒有集合
	public Department(String name, String des) {
		super(name, des);
	}
	
	//add , remove 就不用寫了,因爲他是葉子節點
	@Override
	public String getName() {
		return super.getName();
	}
	
	@Override
	public String getDes() {
		return super.getDes();
	}
	
	@Override
	protected void print() {
		System.out.println(getName());
	}
}

Client


public class Client {

	public static void main(String[] args) {
		
		//從大到小創建對象 學校
		Component university = new University("清華大學", " 中國頂級大學 ");
		
		//創建 學院
		Component computerCollege = new College("計算機學院", " 計算機學院 ");
		Component infoEngineercollege = new College("信息工程學院", " 信息工程學院 ");
		
		
		//創建各個學院下面的系(專業)
		computerCollege.add(new Department("軟件工程", " 軟件工程不錯 "));
		computerCollege.add(new Department("網絡工程", " 網絡工程不錯 "));
		computerCollege.add(new Department("計算機科學與技術", " 計算機科學與技術是老牌的專業 "));
		
		//
		infoEngineercollege.add(new Department("通信工程", " 通信工程不好學 "));
		infoEngineercollege.add(new Department("信息工程", " 信息工程好學 "));
		
		//將學院加入到 學校
		university.add(computerCollege);
		university.add(infoEngineercollege);
		
		university.print();
		System.out.println("============================");
		
		//infoEngineercollege.print();
	}

}

運行結果:

--------------清華大學--------------
--------------計算機學院--------------
軟件工程
網絡工程
計算機科學與技術
--------------信息工程學院--------------
通信工程
信息工程

4、組合模式之透明模式

透明模式,是把組合使用的方法放到 Component 類中,不管葉子對象還是樹枝對象都有相同的結構。

這樣做的好處就是 Leaf節點和Composite 節點 對於外界沒有區別,它們具備完全一致的行爲接口。

但因爲 Leaf 類本身不具備 add()remove() 方法的功能,所以實現它是沒有意義的。

UML結構圖如下:
在這裏插入圖片描述

5、組合模式之安全模式

安全模式,是把 Composite節點和 Leaf 節點徹底分開,Composite節點單獨擁有用來組合的方法,這種方法比較安全。

但由於不夠透明,所以 Leaf 節點 和 Composite節點將不具有相同的接口,客戶端的調用需要做相應的判斷,帶來了不便。

UML結構圖如下:
在這裏插入圖片描述

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