Card 03/ 08
Composite Template in Python, Java and TypeScript
One leaf, one composite, and an operation that recurses through a small tree.
The Composite template is the pattern in its pure form, with the participant names from the class diagram and no domain. Each leaf's operation returns its name, and each composite's returns its own name with its children's results in brackets, so the output shows the shape of the tree. The steps add each participant in Python, and the tabs give the complete program in three languages, each with its output.
Building the template one participant at a time
Component
The interface every node shares.
class Component(ABC):
@abstractmethod
def operation(self) -> str: ...Leaf
A node that answers for itself.
class Leaf(Component):
def operation(self) -> str:
return self._nameComposite
A node that holds components and asks each one.
class Composite(Component):
def add(self, child: Component) -> None:
self._children.append(child)
def operation(self) -> str:
inner = ", ".join(child.operation() for child in self._children)
return f"{self._name}({inner})"Client
Calls operation on a leaf, a composite, and a composite holding a composite.
client(Leaf("A"))
client(branch)
client(root)The complete template
from abc import ABC, abstractmethod
class Component(ABC):
@abstractmethod
def operation(self) -> str: ...
class Leaf(Component):
def __init__(self, name: str) -> None:
self._name = name
def operation(self) -> str:
return self._name
class Composite(Component):
def __init__(self, name: str) -> None:
self._name = name
self._children: list[Component] = []
def add(self, child: Component) -> None:
self._children.append(child)
def operation(self) -> str:
inner = ", ".join(child.operation() for child in self._children)
return f"{self._name}({inner})"
def client(component: Component) -> None:
print(component.operation())
branch = Composite("Branch")
branch.add(Leaf("B"))
branch.add(Leaf("C"))
root = Composite("Root")
root.add(Leaf("A"))
root.add(branch)
client(Leaf("A"))
client(branch)
client(root)A
Branch(B, C)
Root(A, Branch(B, C))import java.util.ArrayList;
import java.util.List;
public class CoTemplate {
static void client(Component component) {
System.out.println(component.operation());
}
public static void main(String[] args) {
Composite branch = new Composite("Branch");
branch.add(new Leaf("B"));
branch.add(new Leaf("C"));
Composite root = new Composite("Root");
root.add(new Leaf("A"));
root.add(branch);
client(new Leaf("A"));
client(branch);
client(root);
}
}
interface Component {
String operation();
}
class Leaf implements Component {
private final String name;
Leaf(String name) {
this.name = name;
}
public String operation() {
return name;
}
}
class Composite implements Component {
private final String name;
private final List<Component> children = new ArrayList<>();
Composite(String name) {
this.name = name;
}
void add(Component child) {
children.add(child);
}
public String operation() {
List<String> parts = new ArrayList<>();
for (Component child : children) {
parts.add(child.operation());
}
return name + "(" + String.join(", ", parts) + ")";
}
}A
Branch(B, C)
Root(A, Branch(B, C))interface Component {
operation(): string;
}
class Leaf implements Component {
constructor(private readonly name: string) {}
operation(): string {
return this.name;
}
}
class Composite implements Component {
private readonly children: Component[] = [];
constructor(private readonly name: string) {}
add(child: Component): void {
this.children.push(child);
}
operation(): string {
const inner = this.children.map((child) => child.operation()).join(", ");
return `${this.name}(${inner})`;
}
}
function client(component: Component): void {
console.log(component.operation());
}
const branch = new Composite("Branch");
branch.add(new Leaf("B"));
branch.add(new Leaf("C"));
const root = new Composite("Root");
root.add(new Leaf("A"));
root.add(branch);
client(new Leaf("A"));
client(branch);
client(root);A
Branch(B, C)
Root(A, Branch(B, C))The three lines of output come from the same client function. The first is a single leaf, the second a composite of two leaves, and the third a composite that holds a leaf and the second composite. Nothing in client or in Composite.operation mentions depth; the recursion follows the tree because each child is asked the same question as its parent.
← → move through sections and cards