Design Pattern: Composite
We can consider a single type or a composition of related types to be the same by:
- Creating a new type, usually an interface, to represent them, called Component.
- Allowing recursive structure, meaning Component can contain other child Components. Components within this structure are called Composite, while those without any children are called Leaf.
When to Use
- When representing hierarchical systems.
- When disregarding the difference between a single object and a composition of objects, treating them all as a Component.
Implementation
Structure
Let's take the example of a UI framework (something like React). UIComponent
represents all types of components such as buttons, text, etc. We also have Popup
, which is a more complex component, composed of a button and a text, making it a Composite.
Sample Code
Component interface:
type UIComponent interface {
Render()
}
Some Leaf types:
type Text struct{}
func (t *Text) Render() {
fmt.Print("hello")
}
type Button struct{}
func (b *Button) Render() {
fmt.Print("button: ")
}
Composite:
type Popup struct {
children []UIComponent
}
func (p *Popup) Render() {
for _, c := range p.children {
c.Render()
}
}
Usage:
text := &Text{}
button := &Button{}
popup := &Popup{
children: []UIComponent{button, text},
}
popup.Render()
// Output:
// button: hello
This pattern offers a way to treat individual objects and compositions uniformly, providing a unified way to work with both. Moreover, we can freely switch the types behind UIComponent
interface without affecting the users.
Testing
This is a pure pattern for building a structure, so I think we can skip this part 😇
Related patterns
Chain Of Responsibility
If we add the parent UIComponent
field to UIComponent
interface, we can create a usable structure for the Chain Of Responsibility pattern. Check out the pattern's article for more details.
Iterator
Iterator can be used to iterate through each component in the Composite structure.
Visitor
Helps gather the logic of the components in one place instead of being scattered across Composites and Leaves.
Decorator
Often used in conjunction with Composite. Check out the Decorator Pattern for more details.