GoLang設計模式20 – 組合模式

定義

組合模式是一種結構型設計模式。

當我們想把一組對象當做一個整體來處理時就可以考慮使用組合模式。

組合模式被視為是接口型設計模式是因為它將一組對象組裝為一個樹狀結構。這個樹狀結構中的每個獨立組件都可以用同樣的方式來處理——無論它們是複雜的還是原始的。

以計算機操作系統中的文件系統為例。在文件系統中有文件(File)和文件夾(Folder)兩類對象,在常見的各種使用場景中,它們的處理方式都差不多是一樣的。接下來我們會依據文件系統對組合模式做更詳細的闡釋。

什麼時候使用

一、當從調用方的角度看來,組裝體和獨立組件需要以同樣的方式來處理時可以使用組合模式

在文件系統中這個例子中,假設我們需要通過關鍵字來搜索文件。這個搜索操作通常會對文件和文件夾同時進行:

  • 對於一個文件來說,會從文件的內容中進行關鍵字檢索
  • 對於一個文件夾來說,會使用關鍵字遞歸遍歷檢索文件夾中的每個文件

二、當組裝體和獨立組件可以組成一個樹狀結構時可以使用組合模式

文件系統中的文件夾和文件顯然是可以組成樹狀結構的。

UML Diagram

類圖如下:

介紹下類圖中的各個組成部分:

  • 組件(Component):一個接口,定義了組裝體和葉子對象的共同操作
  • 組裝體(Composite):Component接口的實現,包含了一組子組件
  • 葉子(Leaf):樹結構中最基礎的對象,也實現了Component接口

文件系統對應的UML類圖如下:

代碼

Component interface component.go

type component interface {
	search(string)
}

Composite folder.go

type folder struct {
	components []component
	name       string
}

func (f *folder) search(keyword string) {
	fmt.Printf("Serching recursively for keyword %s in folder %s\n", keyword, f.name)
	for _, composite := range f.components {
		composite.search(keyword)
	}
}

func (f *folder) add(c component) {
	f.components = append(f.components, c)
}

Leaf file.go

type file struct {
	name string
}

func (f *file) search(keyword string) {
	fmt.Printf("Searching for keyword %s in file %s\n", keyword, f.name)
}

func (f *file) getName() string {
	return f.name
}

client main.go

func main() {
	file1 := &file{name: "File1"}
	file2 := &file{name: "File2"}
	file3 := &file{name: "File3"}
	folder1 := &folder{
		name: "Folder1",
	}
	folder1.add(file1)
	folder2 := &folder{
		name: "Folder2",
	}
	folder2.add(file2)
	folder2.add(file3)
	folder2.add(folder1)
	folder2.search("rose")
}

代碼已上傳至GitHub: zhyea / go-patterns / composite-pattern

END!!!