Golang Composite Pattern

In this post, we will show how to implement a Composite design pattern in Golang with an example.

Composite is a structural design pattern that lets you compose objects into tree structures and then work with these structures as if they were individual objects.

A composite is a group of similar objects in a single object. Objects are stored in a tree form to persist the whole hierarchy. The composite pattern is used to change a hierarchical collection of objects. The composite pattern is modeled on a heterogeneous collection. New types of objects can be added without changing the interface and the client code. 

You can use the composite pattern, for example, for UI layouts on the web, for directory trees, and for managing employees across departments. The pattern provides a mechanism to access the individual objects and groups in a similar manner.

Composite Pattern Class Diagram

The below diagram shows the generic structure of the Composite Pattern:
The composite pattern comprises the component interface, component class, composite,and client:
  • The Component interface defines the default behavior of all objects and behaviors for accessing the components of the composite.
  • The Composite and component classes implement the component interface.
  • The Client interacts with the component interface to invoke methods in the composite.

Golang Composite Pattern Implementation

Consider we have below components based on the above class diagram:
  • The IComposite interface with the perform() method.
  • BranchClass that implements IComposite and has the addLeaf(), addBranch(), and perform() methods. The Leaflet class implements IComposite with the perform() method. 
  • BranchClass has a one-to-many relationship with leafs and branches.
Let's create a file named "composite.go" and add the following source code to it:

package main

// importing fmt package
import (
	"fmt"
)

// IComposite interface
type IComposite interface {
	perform()
}

// Leaflet struct
type Leaflet struct {
	name string
}

// Leaflet class method perform
func (leaf *Leaflet) perform() {

	fmt.Println("Leaflet " + leaf.name)
}

// Branch struct
type Branch struct {
	leafs    []Leaflet
	name     string
	branches []Branch
}

// Branch class method perform
func (branch *Branch) perform() {

	fmt.Println("Branch: " + branch.name)
	for _, leaf := range branch.leafs {
		leaf.perform()
	}

	for _, branch := range branch.branches {
		branch.perform()
	}
}

// Branch class method add leaflet
func (branch *Branch) add(leaf Leaflet) {
	branch.leafs = append(branch.leafs, leaf)

}

//Branch class method addBranch branch
func (branch *Branch) addBranch(newBranch Branch) {

	branch.branches = append(branch.branches, newBranch)
}

//Branch class  method getLeaflets
func (branch *Branch) getLeaflets() []Leaflet {
	return branch.leafs
}

// main method
func main() {

	var branch = &Branch{name: "branch 1"}

	var leaf1 = Leaflet{name: "leaf 1"}
	var leaf2 = Leaflet{name: "leaf 2"}

	var branch2 = Branch{name: "branch 2"}

	branch.add(leaf1)
	branch.add(leaf2)
	branch.addBranch(branch2)

	branch.perform()

}


Output:

G:\GoLang\examples>go run composite.go
Branch: branch 1
Leaflet leaf 1
Leaflet leaf 2
Branch: branch 2

Comments