組合模式

摘要

  本文通過簡潔的模式描述,應用場景的詳細代碼實現,以及匹配的UML,詳解介紹了組合模式的原理及應用。本文可幫助讀者快速掌握組合模式,以便工作學習中使用組合模式。

一、組合模式

  在我們的生活中,很多事物都有一個組織架構的分層現象。比如一個國家的組織結構:國家–省份–市--縣–鎮--村–人,其中除國家是唯一對象之外,其它部分都是多個對象實體;再比如一個集團的組織架構:集團–一級公司–二級公司–部門–小組–程序員,同樣,除集團是唯一對象之外,其它部分都可以是多個實體。這兩個例子中還有一個共同的特點,他們的組織架構中最後一個對象都是不可再分的,不會再有子組織結構。
  在組織結構中,如果上層有消息需要通知到最底層時,每一層的任務都是將消息通知到下一層,比如集團級只與一級公司交互,再由一級公司與二級公司交互,由此類推,一直到小組與程序員交互,在這個交互的過程中,集團並沒有與程序員直接交互,所以實現了集團與程序員之間的解耦操作,方便了其內部組織結構的變動,如程序員還了一批人,從組織架構、公司運行上來說並沒有什麼影響。同樣,單個部門換掉,也不會導致該組織架構的大量改動,保證了“開閉原則”,也體現了“職責單一原則”,只是部門級以下的成員會受到影響,他們將不再接收到上級的消息,或將他們轉入 其它部門。
  在程序的世界裏,有一種熟悉的數據結構——樹,樹結構就類似於上面組織結構。根節點只有一個,可以有多個子節點,也可以多個葉節點,但葉節點不能有子節點或子葉節點。組合模式將各個對象的之間的組織結構封裝起來,一是爲了保證組織架構不會被破壞,二是爲了方便第三方的使用,第三方不用清楚組織架構是怎樣,他只需要對某個節點進行操作。

二、組合模式的實現

2.1 場景設計

  對於組合模式,暫沒有想到身邊的具體實例,所以本文就以節點和葉節點的命名方式來實現組合模式。從上面的解析中可知:根節點只有一個,可以有多個子節點,也可以多個葉節點,但葉節點不能有子節點或子葉節點。所以節點可以看成是一個容器。在消息的傳送中,節點和葉節點都能收到消息,所以他們又具有相同的功能,所以節點和葉節點可以共同繼承與一個共同的藉口或抽象類。

2.2 代碼實現

2.2.1 Component 抽象

package ft.patterns.composite;

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

public abstract class Component {
	public Component() {
		this.leafList = new ArrayList<Component>();
	}

	List<Component> leafList;
	
	void add(Component leaf){
		throw new UnsupportedOperationException();
	};
	
	boolean remove(Component leaf) {
		throw new UnsupportedOperationException();
	};
	
	void execute() {
		throw new UnsupportedOperationException();
	}
}

2.2.2 Composite 節點類

package ft.patterns.composite;

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

public class Composite extends Component{
	private String name;
	private List<Component> componentList;

	public Composite(String name) {
		super();
		this.name = name;
		componentList = new ArrayList<Component>();
	}
	
	
	@Override
	void add(Component leaf) {
		if(leaf != null)
			componentList.add(leaf);
	}

	@Override
	boolean remove(Component leaf) {
		int result = componentList.indexOf(leaf);
		if(result != -1) {
			componentList.remove(result);
			return true;
		}
		return false;
	}

	@Override
	void execute() {
		System.out.println("hello "+name);
		for(Component temp : componentList) {
			temp.execute();
		}
	}
}

2.2.3 Leaf 葉節點類

package ft.patterns.composite;

public class Leaf extends Component{
	private String name;
	public Leaf(String name){
		super();
		this.name = name;
	}
	@Override
	void execute() {
		System.out.println("hello " + name);
	}
}

2.2.4 Main 測試類

package ft.patterns.composite;

public class Main {
	public  static void main(String[] args) {
		Component root = new Composite("root");
		Component leaf1 = new Leaf("leaf1");
		Component leaf2 = new Leaf("leaf2");
		Component component1 = new Composite("component1");
		Component leaf3 = new Leaf("leaf3");
		Component leaf4 = new Leaf("leaf4");
		Component leaf5 = new Leaf("leaf5");
		Component component2 = new Composite("component2");
		Component leaf6 = new Leaf("leaf6");
		Component component3 = new Composite("component3");
		
		component3.add(leaf3);
		component3.add(leaf4);
		component1.add(leaf2);
		component1.add(component3);
		
		component2.add(leaf5);
		component2.add(leaf6);
		
		root.add(component1);
		root.add(component2);
		root.add(leaf1);
		System.out.println("########################");
		root.execute();
		System.out.println("########################");
		component1.execute();
		System.out.println("########################");
		component3.execute();
		System.out.println("########################");
		component2.execute();	
	}
}

2.2.5 測試結果

########################
hello root
hello component1
hello leaf2
hello component3
hello leaf3
hello leaf4
hello component2
hello leaf5
hello leaf6
hello leaf1
########################
hello component1
hello leaf2
hello component3
hello leaf3
hello leaf4
########################
hello component3
hello leaf3
hello leaf4
########################
hello component2
hello leaf5
hello leaf6

三、組合模式的UML圖

組合模式UML類圖

發佈了21 篇原創文章 · 獲贊 0 · 訪問量 1820
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章