【Golang】设计模式 - Structural - Composite

Posted by 西维蜀黍 on 2021-09-18, Last Modified on 2023-08-23

Composite Pattern

Let’s try to understand the Composite pattern with an example of an operating system’s file system. In the file system, there are two types of objects: files and folders. There are cases when files and folders should be treated to be the same way. This is where the Composite pattern comes in handy.

Imagine that you need to run a search for a particular keyword in your file system. This search operation applies to both files and folders. For a file, it will just look into the contents of the file; for a folder, it will go through all files of that folder to find that keyword.

When to Use

  • Composite Design pattern makes sense to use in cases when the composite and individual object needs to be treated in the same way from a client perspective.

​ – In our example above of the file system, let’s say search operation of a particular keyword needs to be executed. Now, this search operation applies to both File and Folder. For a File, it will just look into the contents of the file and for a Folder, it will go through all files in the hierarchy in that folder to find that keyword

  • Use this pattern when the composite and individual object form a tree-like structure

​ – In our example, File and Folder do form a tree structure

Refer to https://swsmile.info/post/design-pattern-composite-pattern/ for Composite pattern.

file.go: Component interface

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
}

folder.go: Composite

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

component.go: Leaf

package main

type component interface {
    search(string)
}

main.go: Client code

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: Execution result

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

Reference