春のセール
Composite

Composite を Go で

Composite 構造に関するデザインパターンの一つで オブジェクトを木のような構造に構成し あたかも単一のオブジェクトであるかのように扱えるようにします

Composite は ツリー構造の構築を必要とする問題の大部分の解決策として かなりの人気を得るようになりました Composite の大きな特徴は ツリー構造全体でメソッドを再帰的に実行し 結果をまとめあげることです

概念的な例

オペレーティング・システムのファイルシ・ステムを例に取って Composite パターンを理解してみましょう ファイル・ システムには ファイルとフォルダーという 2 種類のオブジェクトが存在します ファイルとフォルダーを同じように扱う必要がある場合があります ここで Composite パターンが役に立ちます

ファイル・システムで特定のキーワードを使った検索を実行する必要があるとします この検索の作業は ファイルとフォルダーの両方に適用されます ファイルの場合は ファイルの内容を調べるだけです フォルダーの場合は そのフォルダーのすべてのファイルに対してキーワード検索を行います

component.go: コンポーネントのインターフェース

package main

type Component interface {
	search(string)
}

folder.go: コンポジット

package main

import "fmt"

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)
}

file.go: リーフ

package main

import "fmt"

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
}

main.go: クライアント・コード

package main

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")
}

output.txt: 実行結果

Serching recursively for keyword rose in folder Folder2
Searching for keyword rose in file File2
Searching for keyword rose in file File3
Serching recursively for keyword rose in folder Folder1
Searching for keyword rose in file File1

他言語での Composite

Composite を C# で Composite を C++ で Composite を Java で Composite を PHP で Composite を Python で Composite を Ruby で Composite を Rust で Composite を Swift で Composite を TypeScript で