CODESAMPLE
Composite - Go
The Composite pattern allows you to treat individual objects and compositions of objects uniformly. It’s used when you have hierarchical relationships where you want to perform operations on both individual “leaves” and complex “branches” in the same way. In this Go example, we model a file system. Entry is the component interface, implemented by both File (leaf) and Directory (composite). Directory contains a list of Entry interfaces, allowing it to represent a hierarchy. The Name() and Size() methods are defined on the interface and are implemented by each concrete type, demonstrating the uniform treatment of files and directories. This approach leans on interfaces, a core part of Go’s type system, to achieve polymorphism and adheres to Go’s composition-over-inheritance philosophy.
package main
import "fmt"
// Entry is the component interface
type Entry interface {
Name() string
Size() int
}
// File represents a leaf node in the file system
type File struct {
name string
size int
}
func (f *File) Name() string {
return f.name
}
func (f *File) Size() int {
return f.size
}
// Directory represents a composite node in the file system
type Directory struct {
name string
entries []Entry
}
func (d *Directory) Name() string {
return d.name
}
func (d *Directory) Size() int {
totalSize := 0
for _, entry := range d.entries {
totalSize += entry.Size()
}
return totalSize
}
func (d *Directory) AddEntry(entry Entry) {
d.entries = append(d.entries, entry)
}
func main() {
root := &Directory{name: "root"}
file1 := &File{name: "file1", size: 10}
file2 := &File{name: "file2", size: 20}
subdir := &Directory{name: "subdir"}
file3 := &File{name: "file3", size: 5}
root.AddEntry(file1)
root.AddEntry(file2)
root.AddEntry(subdir)
subdir.AddEntry(file3)
fmt.Printf("Name: %s, Size: %d\n", root.Name(), root.Size())
fmt.Printf("Name: %s, Size: %d\n", subdir.Name(), subdir.Size())
fmt.Printf("Name: %s, Size: %d\n", file1.Name(), file1.Size())
}