程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> OO模式-Composite

OO模式-Composite

編輯:C++入門知識

OO模式-Composite


組合模式也叫做“部分-整體”模式,這樣其實定義也就很明顯了,正好和數據結構的知識相對應,把對象組合成樹形結構以表示“部分-整體”的層次結構。

先看類圖:

\

首先分析一下這個類圖,Leaf和CompZ喎?http://www.Bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vc2l0ZcrHzayxsrXEo6y2vMrHvMyz0Li4wOBDb21wb25lbnSjrNPW0vLOqkNvbXBvbmVudNbQtObU2kxlYWbX08Dgo6zL+dLUy/u6zUNvbXBvbmVudLu5tObU2tfFvtu6z7nYz7U8L3A+CjxwPjxicj4KPC9wPgo8cD4gICAgIL7Z0ru49rrcs6O8+7XEwP3X06OsztLDx8zszOy21NfFtefE1KOsus2499bWzsS8/qOszsS8/rzQtPK9u7XAo6zV4rK7vs3Kx9K7uPa63LrDtdjX6brPxKPKvcLwo788L3A+CjxwPjxzdHJvbmc+wLS/tL+0wODNvKO6PC9zdHJvbmc+PC9wPgo8cD48aW1nIHNyYz0="http://www.2cto.com/uploadfile/Collfiles/20141014/20141014092238331.png" alt="\">

來看看具體的實現代碼:

AbstractFile為組合中的對象聲明接口,實現所有類共有接口的默認行為。

package composite;

import java.util.*;    //添加引用

public abstract class AbstractFile {
	protected String name; // 定義name字段

	public void printName() {
		System.out.println(name);
	}

	// 通常都用add和remove方法來提供增加或移除樹葉或樹枝的功能
	public abstract boolean addChild(AbstractFile file); // 增加

	public abstract boolean removeChild(AbstractFile file); // 移除
	// 一個集合,存放摘要文件的子文件的對象

	public abstract List getChildren();
}
File為子類文件,繼承父類,也是樹中所謂的葉子節點,葉子節點是沒有子節點的,所以父類所謂的方法並不能實現,返回true和null

package composite;

import java.util.*;

public class File extends AbstractFile {
	public File(String name) {
		this.name = name;
	}
//文件並沒有添加的能力,它只是一個單獨的個體
	public boolean addChild(AbstractFile file) {
		return false;
	}
//對於文件本身,已經是葉子節點了,所以也無刪除子文件的功能
	public boolean removeChild(AbstractFile file) {
		return false;
	}

	// 由於File已經是葉子節點了,所以就不存在集合這一說,所以這個方法返回的是空值
	public List getChildren() {
		return null;
	}
}
Folder為子類文件夾,同樣也繼承於父類,但是此類只是一個普通的節點,裡邊依舊包含葉子節點。

package composite;

import java.util.*;

public class Folder extends AbstractFile {
	
	private List childList ;

	public Folder(String name) {
		this.name = name;
		//用來建立一個集合保存子文件
		this.childList = new ArrayList();
	}
	//添加子文件
	public boolean addChild(AbstractFile file) {
		return childList.add(file);
	}
	//刪除子文件
	public boolean removeChild(AbstractFile file) {
		return childList.remove(file);
	}

	// 子類的返回類型應該和父類的定義保持一致
	public List getChildren() {
		return childList;
	}

}
最後來看看客戶端是如何調用和打印的

package composite;

import java.util.List;

public class Client {
	public static void main(String[] args) {
		// TODO 自動生成的方法存根
		// 構造一個樹形的文件、目錄結構
		AbstractFile rootFolder = new Folder("c:\\");
		AbstractFile compositeFolder = new Folder("composite");
		AbstractFile windowsFolder = new Folder("windows");
		AbstractFile file = new File("TestComposite.java");

		rootFolder.addChild(compositeFolder);
		rootFolder.addChild(windowsFolder);
		compositeFolder.addChild(file);
		// 打印目錄文件樹
		printTree(rootFolder);
	}

	private static void printTree(AbstractFile ifile) {
		ifile.printName();
		List children = ifile.getChildren();
		if (children == null)
			return;
		for (AbstractFile file : children) {
			printTree(file); // 打印方法的調用
		}
	}
}

透明方式與安全方式

在File子類中,他所謂的各種方法都是不實行的,但是卻依舊存在,這種方式就叫做“透明方式”;這樣做的好處就是葉子節點和枝節點對於外界沒有區別,它們具備完全一致的行為接口;但是問題也會很明顯的,那就是在File中那些所謂的方法的存在是毫無意義的;

如果不想讓其做無用功,也就是把File子類中的無意義的方法都去掉,這種方式叫做“安全方式”;但是由於是不透明的,所以他們就不能具有一致的接口了,這樣反而增加了其復雜性,客戶端的調用需要再增加其相應的判斷。


什麼時候使用組合模式?

1)需求中體現的是“部分-整體”的層次的結構時,使用此模式;

2)用戶希望忽略組合對象與單個對象的不同,統一地使用組合結構中的所有的對象的時候,使用此模式;


最後總結:

每個模式其實都是需要慢慢理解的,真正的懂得了它的精髓所在,那當再看到類似的字眼的時候就會有親近的感覺,對於組合模式總結為以下幾點:

組合模式提供一個結構,可同時包容個別對象和組合對象; 允許客戶對個別對象以及組合對象一視同仁; 組合結構內的任意對象都稱為組件,組件可以是組合,也可以是葉子節點; 在實現組合模式時,有許多設計上的折衷。這時候就要就情況選擇透明方式還是安全方式了!


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved