Composite Design
When to Deploy (Problem)
When to Deploy (Problem)
- When the problem requires a primitive data structure into a composite objects.
- When the problem requires recursive composition approach.
Checklist
Checklist
- Ensure the problem is representing "whole" part of the hierarchical relationship.
- Able to ignore the compositions of objects and individual objects (container vs containees).
- All container and containee classes declare an "is a" relationship to the interface.
- All container classes declare a one-to-many "has a" relationship to the interface.
- Container classes leverage polymorphism to delegate to their containee objects.
Example Codes (Solution)
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)
Expected Outcome (Consequences)
- It makes client simple due to treating objects and composites uniformly.
- Easy to add new kinds of components.
- Generalize the overall design.