天天看點

設計模式初探-組合模式

組合模式,英文為COMPOSITE模式,屬于對象結構型模式。用于組合多個對象形成樹形結構以表示具有“整體—部分”關系的層次結構。組合模式對單個對象(即葉子對象)群組合對象(即容器對象)的使用具有一緻性。通常樹形結構,比如公司組織結構,檔案目錄,系統菜單,xml檔案解析等都可以采用組合模式實作。

一、适用場景

1、在具有整體和部分的層次結構中,希望通過一種方式忽略整體與部分的差異,用戶端可以一緻地對待它們。

2、 在一個使用面向對象語言開發的系統中需要處理一個樹形結構。

3、在一個系統中能夠分離出葉子對象和容器對象,而且它們的類型不固定,需要增加一些新的類型。

二、UML圖

設計模式初探-組合模式

組合模式的關鍵是定義了一個抽象構件類,它既可以代表葉子,又可以代表容器,而用戶端針對該抽象構件類進行程式設計,無須知道它到底表示的是葉子還是容器,可以對其進行統一處理。同時容器對象與抽象構件類之間還建立一個聚合關聯關系,在容器對象中既可以包含葉子,也可以包含容器,以此實作遞歸組合,形成一個樹形結構。

三、Java實作

package study.patterns.composite;

import java.util.ArrayList;
import java.util.List;
/**
 * 組合模式:組合多個對象形成樹形結構以表示具有“整體—部分”關系的層次結構。
 * 組合模式對單個對象(即葉子對象)群組合對象(即容器對象)的使用具有一緻性。
 * @author qbg
 */
public class CompositePattern {
	public static void main(String[] args) {
		IMessage forum = new Forum("灌水區", "admin");
		IMessage m1 = new PostMessage("張三", "大象進醫院了!!!");
		IMessage m2 = new PostMessage("李四", "怎麼可能?");
		IMessage m3 = new PostMessage("張三", "怎麼不可能?!大象踩着螞蟻,然後骨折了!!!");
		m1.add(m2);
		m2.add(m3);
		forum.add(m1);
		forum.print();
	}
}
/**
 * 論壇版塊,文章抽象接口。
 */
interface IMessage{
	public void add(IMessage message);
	public void delete(int i);
	public IMessage getChild(int i);
	public void print();
}
/**
 * 論壇文章:原始帖或回帖
 */
class PostMessage implements IMessage{
	private String content; //内容
	private String author; //發帖人
	private List<IMessage> messages = new ArrayList<IMessage>();//回帖
	
	public PostMessage(String author,String content){
		this.author = author;
		this.content = content;
	}
	
	@Override
	public void add(IMessage message) {
		messages.add(message);
	}

	@Override
	public void delete(int i) {
		if(i>messages.size()){
			throw new IllegalArgumentException("索引越界...");
		}
		messages.remove(i);
	}

	@Override
	public IMessage getChild(int i) {
		return messages.get(i);
	}
	
	@Override
	public void print() {
		System.out.println(author+"說:"+content);
		//遞歸調用成員構件的業務方法實作
		for(IMessage message : messages){
			message.print();
		}
	}
}
/**
 * 論壇版塊:由相應文章組成
 */
class Forum implements IMessage{
	private String name; //版塊名
	private String admin;//版主
	private List<IMessage> messages = new ArrayList<IMessage>();//文章
	
	public Forum(String name,String admin){
		this.name = name;
		this.admin = admin;
	}
	
	@Override
	public void add(IMessage message) {
		messages.add(message);
	}

	@Override
	public void delete(int i) {
		if(i>messages.size()){
			throw new IllegalArgumentException("索引越界...");
		}
		messages.remove(i);
	}

	@Override
	public IMessage getChild(int i) {
		return messages.get(i);
	}

	@Override
	public void print() {
		System.out.println("版塊:"+name+",管理者:"+admin);
		System.out.println("文章内容:");
		//遞歸調用成員構件的業務方法實作
		for(IMessage message : messages){
			message.print();
		}
	}
}
           

運作結果:

版塊:灌水區,管理者:admin
文章内容:
張三說:大象進醫院了!!!
李四說:怎麼可能?
張三說:怎麼不可能?!大象踩着螞蟻,然後骨折了!!!
           

四、模式優缺點

優點:

1、組合模式可以清楚地定義分層次的複雜對象,表示對象的全部或部分層次,它讓用戶端忽略了層次的差異,友善對整個層次結構進行控制。

2、用戶端可以一緻地使用一個組合結構或其中單個對象,不必關心處理的是單個對象還是整個組合結構,簡化了用戶端代碼。

3、在組合模式中增加新的容器構件和葉子構件都很友善,無須對現有類庫進行任何修改,符合“開閉原則”。

4、組合模式為樹形結構的面向對象實作提供了一種靈活的解決方案,通過葉子對象和容器對象的遞歸組合,可以形成複雜的樹形結構,但對樹形結構的控制卻非常簡單。

缺點:

1、 在增加新構件時很難對容器中的構件類型進行限制。有時候我們希望一個容器中隻能有某些特定類型的對象,例如在某個檔案夾中隻能包含文本檔案,使用組合模式時,不能依賴類型系統來施加這些限制,因為它們都來自于相同的抽象層,在這種情況下,必須通過在運作時進行類型檢查來實作,這個實作過程較為複雜。