NOTE

Composite Pattern

Composite-pattern notes for tree-shaped whole/part structures, with Java and Go file-tree examples.

Software Architecture & Engineering1 min readhistorical

This is a historical learning note and may contain outdated or incomplete understanding.

1. Definition

Suitable for tree-shaped whole/part structures. It unifies access to leaf and composite nodes and can apply an operation to all child nodes.

2. UML

PlantUML 图表

3. Java

3.1. Client

public class Client
{
    public static void main(String[] args)
    {
        Directory file = new Directory();
        file.addChild(new ImageFile());

        file.killVirus();
    }
}

3.2. Objects

public class ImageFile implements File
{
    @Override
    public void killVirus()
    {
        System.out.println("scan image file");
    }
}
public class Directory implements File
{
    private List<File> children = new ArrayList<>();

    public void addChild(File file)
    {
        this.children.add(file);
    }

    public void removeChild(File file)
    {
        this.children.remove(file);
    }


    @Override
    public void killVirus()
    {
        System.out.println("scan directory");
        // Natural recursion
        this.children.forEach(File::killVirus);
    }
}
public interface File
{
    void killVirus();
}

4. Golang

4.1. Objects

/* Parent interface for leaf and tree nodes */
type File interface {
	KillVirus()
	GetName() string
}

type abstractFile struct {
	Name string
}

func (a *abstractFile) GetName() string {
	return a.Name
}

/* Leaf node */
type ImageFile struct {
	abstractFile
}

func NewImageFile(name string) *ImageFile {
	return &ImageFile{abstractFile: abstractFile{Name: name}}
}

func (i *ImageFile) KillVirus() {
	fmt.Printf("ImageFile[%s] scan\n", i.GetName())
}

/* Tree node */
type Directory struct {
	Children []File
	abstractFile
}

func NewDirectory(name string) *Directory {
	return &Directory{Children: make([]File, 0), abstractFile: abstractFile{Name: name}}
}

func (d *Directory) KillVirus() {
	fmt.Printf("Directory[%s] scan\n", d.GetName())

	for _, v := range d.Children {
		v.KillVirus()
	}
}

func (d *Directory) AddChild(file File) {
	d.Children = append(d.Children, file)
}

4.2. Client

func main() {
	rootDir := Composite Pattern.NewDirectory("root")
	confDir := Composite Pattern.NewDirectory("config")
	rootDir.AddChild(Composite Pattern.NewImageFile("image-a.jpg"))
	rootDir.AddChild(Composite Pattern.NewImageFile("image-b.jpg"))
	rootDir.AddChild(confDir)
	confDir.AddChild(Composite Pattern.NewImageFile("nginx.conf"))

	rootDir.KillVirus()
}

Discussion

Sign in with GitHub to comment. Discussions are stored as GitHub Issues.View on GitHub