Composite Design

Composite design pattern is where a component has a composite list of its own kind. In another word, the component has many of the similar components as a child list. Example:

  • Employee (component) has a list (composite) of many employee subordinates (components)

Here is the design diagram.

When to Deploy (Problem)

  1. When the problem requires a primitive data structure into a composite objects.
  2. When the problem requires recursive composition approach.


Checklist

  1. Ensure the problem is representing "whole" part of the hierarchical relationship.
  2. Able to ignore the compositions of objects and individual objects (container vs containees).
  3. All container and containee classes declare an "is a" relationship to the interface.
  4. All container classes declare a one-to-many "has a" relationship to the interface.
  5. Container classes leverage polymorphism to delegate to their containee objects.

Example Codes (Solution)

Here is an example of composite design pattern. Notice the Employee structure has a list of subordinates, which is the basis of Employee itself.

package main

import (
        "fmt"
)

type Employee struct {
        name        string
        subordinate []*Employee
        salary      uint64
}

func newEmployee(name string, salary uint64) *Employee {
        return &Employee{
                name:        name,
                subordinate: []*Employee{},
                salary:      salary,
        }
}

func main() {
        dev1 := newEmployee("Conor Lex", 600000)
        dev2 := newEmployee("Luke Lex", 600000)
        manager := newEmployee("Sarah Ting", 1200000)
        manager.subordinate = append(manager.subordinate, dev1)
        manager.subordinate = append(manager.subordinate, dev2)

        ceo := newEmployee("John Smith", 1800000)

        fmt.Printf("CEO: %v\n", ceo)
        fmt.Printf("Manager: %v\n", manager)
        fmt.Printf("Dev 1: %v\n", dev1)
        fmt.Printf("Dev 2: %v\n", dev2)
}

Expected Outcome (Consequences)

  1. It makes client simple due to treating objects and composites uniformly.
  2. Easy to add new kinds of components.
  3. Generalize the overall design.