Go实现组合模式的关键是让叶子和容器节点实现统一Node接口,通过接口+嵌入+方法集表达层次关系;File实现基础行为,Folder聚合Node切片并委托操作,Add方法仅限组合节点,调用方无需类型判断即可统一处理树结构。

用 Go 实现组合模式(Composite Pattern)的关键在于:让叶子节点和容器节点实现同一接口,从而能统一处理树形结构中的任意节点,无需区分“有没有子节点”。Go 没有继承,但靠接口 + 嵌入(embedding)+ 方法集,能干净地表达“整体-部分”的层次关系。
所有节点——无论是文件(叶子)还是文件夹(容器)——都实现同一个接口,比如 Node:
(接口只声明行为,不关心具体是叶子还是组合)
type Node interface {
GetName() string
GetSize() int64
Print(indent string)
}这个接口覆盖了树遍历、统计、展示等常见需求。只要类型实现了这三个方法,它就是合法的树节点。
立即学习“go语言免费学习笔记(深入)”;
比如一个普通文件,它没有子节点,GetSize() 返回自身大小,Print() 不递归:
type File struct {
name string
size int64
}
func (f *File) GetName() string { return f.name }
func (f *File) GetSize() int64 { return f.size }
func (f *File) Print(indent string) {
fmt.Printf("%s? %s (%d bytes)\n", indent, f.name, f.size)
}比如文件夹,它持有子节点切片,并把操作委托给子节点:
type Folder struct {
name string
children []Node // 关键:存的是接口,可混装 File 和 Folder
}
func (f *Folder) GetName() string { return f.name }
func (f *Folder) GetSize() int64 {
var total int64
for _, child := range f.children {
total += child.GetSize()
}
return total
}
func (f *Folder) Print(indent string) {
fmt.Printf("%s? %s\n", indent, f.name)
for _, child := range f.children {
child.Print(indent + " ") // 向下缩进,递归打印
}
}
func (f *Folder) Add(child Node) {
f.children = append(f.children, child)
}注意:Add 是组合节点特有方法,不必塞进 Node 接口——组合模式不要求所有方法对称,只保证公共行为一致。
你可以自由嵌套,代码清晰直观:
root := &Folder{name: "project"}
src := &Folder{name: "src"}
src.Add(&File{name: "main.go", size: 1024})
src.Add(&File{name: "utils.go", size: 512})
root.Add(src)
root.Add(&File{name: "go.mod", size: 128})
fmt.Println("Tree size:", root.GetSize()) // → 1664
root.Print("") // 自动缩进打印整棵树调用方完全不用判断 if folder != nil 或 if file != nil ——所有节点都当 Node 处理,递归逻辑收在 Print 和 GetSize 内部。
基本上就这些。Go 的组合模式不依赖类继承,靠接口契约 + 值/指针接收者 + 切片存接口,轻量又灵活。关键不是“模仿 Java 写法”,而是抓住“统一操作入口”这个本质。
以上就是如何使用Golang实现组合模式_使用Composite Pattern处理树形结构的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号