![Composite](/images/patterns/cards/composite-mini.png?id=a369d98d18b417f255d04568fd0131b8)
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