chiachan
chiachan
Published on 2020-08-29 / 602 Visits
0

Composite模式(组合模式)

什么是组合模式?

  • 组合模式即使容器和内容具有一致性,从而构建递归结构
  • 将容器和内容当做同一种对象对待

示范代码(composite.go)

系统文件目录

package Composite

import "fmt"

// 一致性结构
type Entry interface {
	getName() string
	getSize() int
	printList(prefix string)
}

// 文件
type File struct {
	name string
	size int
}

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

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

func (f *File) getSize() int {
	return f.size
}

func (f *File) printList(prefix string) {
	fmt.Printf("%s/%s\n", prefix, f.toString())
}

func (f *File) toString() string {
	return fmt.Sprintf("%s (%d)", f.getName(), f.getSize())
}

// 文件夹
type Directory struct {
	name   string
	Entrys []Entry
}

func NewDirectory(name string) *Directory {
	return &Directory{
		name: name,
	}
}
func (d *Directory) getName() string {
	return d.name
}

func (d *Directory) getSize() int {
	sum := 0
	for _, e := range d.Entrys {
		sum += e.getSize()
	}
	return sum
}

func (d *Directory) add(entry Entry) {
	d.Entrys = append(d.Entrys, entry)
}

func (d *Directory) printList(prefix string) {
	fmt.Printf("%s/%s\n", prefix, d.toString())
	for _, e := range d.Entrys {
		e.printList(fmt.Sprintf("%s/%s", prefix, d.name))
	}
}

func (d *Directory) toString() string {
	return fmt.Sprintf("%s (%d)", d.getName(), d.getSize())
}

测试用例(composite_test.go)

package Composite

import (
	"fmt"
	"testing"
)

func TestEntry_PrintList(t *testing.T) {
	fmt.Println("Making root entries...")
	rootdir := NewDirectory("root")
	bindir := NewDirectory("bin")
	tmpdir := NewDirectory("tmp")
	usrdir := NewDirectory("usr")
	rootdir.add(bindir)
	rootdir.add(tmpdir)
	rootdir.add(usrdir)
	bindir.add(NewFile("vi", 10000))
	bindir.add(NewFile("latex", 20000))
	rootdir.printList("")

	fmt.Println("")
	fmt.Println("Making user entries...")
	yuki := NewDirectory("yuki")
	hanako := NewDirectory("hanako")
	tomura := NewDirectory("tomura")
	usrdir.add(yuki)
	usrdir.add(hanako)
	usrdir.add(tomura)
	yuki.add(NewFile("index.html", 100))
	yuki.add(NewFile("Composite.md", 200))
	hanako.add(NewFile("flag.text", 300))
	tomura.add(NewFile("game.exe", 400))
	tomura.add(NewFile("README.md", 500))
	rootdir.printList("")
}