The composite pattern is a structural pattern which allows you to create tree structures of objects and treat them as a single object. The tree can contain individual or groups of objects which can be treated in the exact same way. This pattern is useful to represent a hierarchy of objects.
You can find the full example source code here. As an example of the implementation I'm going to create an application that represents a Text Editor.
SimpleText
object, which will be used to render text on the UI.SimpleImage
object, which will be used to render images on the UI.Block
component, which represents a group of objects. I will use this object to create paragraphs.render
.interface Component {
render: () => void;
}
class SimpleText implements Component {
private text: string;
constructor(text: string) {
this.text = text;
}
public render() {
console.log("Rendering text:", this.text);
}
}
class SimpleImage implements Component {
private src: string;
constructor(src: string) {
this.src = src;
}
public render() {
console.log("Rendering image:", this.src);
}
}
class Block implements Component {
private children: Component[] = [];
public add(child: Component): void {
this.children.push(child);
}
public render() {
this.children.forEach((child) => child.render());
}
}
As you can see, if we render
the simple objects like SimpleText
or SimpleImage
they will execute some logic implemented in those classes. But if we render
the Block
component it will call the render
function of all of it's children. We can interact with the tree of objects as it was a single object if we interact with the root object.
const block = new Block();
block.add(new SimpleText("Hello"));
block.add(new SimpleImage("https://example.com/image.png"));
block.render();
/*
Output:
Rendering text: Hello
Rendering image: https://example.com/image.png
*/
A more complex example of nested blocks would be:
const nestedBlock = new Block();
nestedBlock.add(new SimpleText("Hello, check the following image:"));
nestedBlock.add(new SimpleImage("https://example.com/image.png"));
const mainBlock = new Block();
mainBlock.add(nestedBlock);
mainBlock.add(new SimpleText("Thanks for reading!"));
mainBlock.render();
/*
Output:
Rendering text: Hello, check the following image:
Rendering image: https://example.com/image.png
Rendering text: Thanks for reading!
*/