结构型 组合模式

为什么需要组合模式

组合模式是把部分和整体(集合)的操作统一化,通常用于树形结构。例如:目录和文件,当大家都有数文件大小的时候可以考虑这种模式,会让代码显得很简洁。

实现

组合模式其实就是巧妙使用了递归,不同的类(实现同一个接口),在调用的时候采用同一种调用方法。例如这里打印路径。

go.mod

module composite

go 1.13

composite.go

package composite

import (
	"bytes"
)

type filenode interface {
	Print(sep string) string
}

type Dir struct {
	name     string
	children []filenode
}

func NewDir(name string) *Dir {
	return &Dir{name: name}
}

func (d *Dir) Add(node filenode) {
	d.children = append(d.children, node)
}

func (d *Dir) Print(sep string) string {
	var buf bytes.Buffer
	buf.WriteString(d.name)
	sep += sep
	for _, node := range d.children {
		// we can make use of the print here
		buf.WriteString("\n")
		buf.WriteString(sep + "|\n")
		buf.WriteString(sep + "->")
		buf.WriteString(node.Print(sep))
	}
	return buf.String()
}

type File struct {
	name string
}

func NewFile(name string) *File {
	return &File{
		name: name,
	}
}

func (f *File) Print(sep string) string {
	return f.name
}

composite_test.go

package composite_test

import (
	"composite"
	"testing"
)

func TestComposite(t *testing.T) {
	dir1 := composite.NewDir("dir1")
	dir1.Add(composite.NewFile("file1"))
	dir2 := composite.NewDir("dir2")
	dir2.Add(composite.NewFile("file2"))
	dir1.Add(dir2)

	expectResult := `dir1
##|
##->file1
##|
##->dir2
####|
####->file2`

	if dir1.Print("#") != expectResult {
		t.Fatal(dir1.Print("#"))
	}
}
Previous
Next