组合模式(Composite Pattern)

未匹配的标注

组合模式是一种结构型设计模式,它允许将对象组合成树形结构来表示部分整体层次结构。组合模式使得客户端能够统一对待单个对象和对象组合,从而可以更加简单和一致地处理它们。

在组合模式中,有两种类型的对象:组合对象和叶子对象。组合对象可以包含其他组合对象和/或叶子对象,而叶子对象则不能包含任何子对象。组合对象和叶子对象都实现了相同的接口,使得客户端可以统一对待它们。

下面是 Go 语言中组合模式的一个示例,其中包含了组合对象(Directory)和叶子对象(File)。

package composite

import "fmt"

// Component 接口定义了组合对象和叶子对象的公共方法。
type Component interface {
    GetName() string
    List(indent int)
}

// File 是叶子对象,它代表文件。
type File struct {
    name string
}

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

func (f *File) List(indent int) {
    fmt.Printf("%s- %s\n", getIndent(indent), f.name)
}

// Directory 是组合对象,它代表文件夹。
type Directory struct {
    name      string
    children  []Component
}

func (d *Directory) GetName() string {
    return d.name
}

func (d *Directory) List(indent int) {
    fmt.Printf("%s+ %s\n", getIndent(indent), d.name)
    for _, child := range d.children {
        child.List(indent + 2)
    }
}

// AddChild 方法用于向文件夹中添加子组件。
func (d *Directory) AddChild(c Component) *Directory {
    d.children = append(d.children, c)

    return d
}

// RemoveChild 方法用于从文件夹中移除子组件。
func (d *Directory) RemoveChild(c Component) *Directory {
    for i, child := range d.children {
        if child == c {
            d.children = append(d.children[:i], d.children[i+1:]...)
            return d
        }
    }

    return d
}

// getIndent 方法返回指定缩进级别的空格字符串。
func getIndent(indent int) string {
    result := ""
    for i := 0; i < indent; i++ {
        result += " "
    }
    return result
}

在上面的代码中,Component 接口定义了组合对象和叶子对象的公共方法,其中 GetName() 方法返回对象的名称,List() 方法用于列出组合对象及其子对象。

File 类型代表叶子对象,它实现了 Component 接口中的方法。Directory 类型代表组合对象,它包含一个子对象列表,可以通过 AddChild() 方法向其中添加子对象,通过 RemoveChild() 方法从其中移除子对象,它也实现了 Component 接口中的方法。

最后,getIndent() 方法用于生成指定缩进级别的空格字符串,用于在列表中展示组合对象。

下面是一个使用组合模式的示例,其中创建了一个包含多个文件和文件夹的文件系统,并打印出文件系统的层次结构:

package main

import "github.com/example/composite"

func main() {
    // 创建文件系统
    root := &Directory{name: "root"}
    documents := &Directory{name: "documents"}
    pictures := &Directory{name: "pictures"}
    music := &Directory{name: "music"}
    file1 := &File{name: "file1.txt"}
    file2 := &File{name: "file2.txt"}
    file3 := &File{name: "file3.txt"}

    root.AddChild(documents).
        AddChild(pictures).
        AddChild(music)
    documents.
        AddChild(file1).
        AddChild(file2)
    pictures.AddChild(file3)

    // 打印文件系统的层次结构
    root.List(0)
}

在上面的代码中,我们首先创建了一个文件系统,其中包含一个根目录(root)和三个子目录(documents、pictures 和 music),以及三个文件(file1.txt、file2.txt 和 file3.txt)。然后,我们将子对象添加到它们的父对象中,形成了一棵树形结构。

最后,我们调用 List() 方法来打印整个文件系统的层次结构。输出结果如下:

+ root
  + documents
    - file1.txt
    - file2.txt
  + pictures
    - file3.txt
  + music

可以看到,文件系统被打印成了树形结构,每个组合对象都以加号开头,每个叶子对象都以短横线开头。这证明了组合模式的优点:它允许客户端统一对待组合对象和叶子对象,并以一种简单和一致的方式处理它们。

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~