El patrón Composite trata elementos individuales y jerarquías completas con la misma interfaz.
1. El Problema de Partida
getCategories devuelve categorías planas de _category.json, pero si el knowledge base creciera para soportar subcategorías (ej. arquitectura-de-software > patrones-diseño > creacionales), la navegación tendría que distinguir con if (hasChildren) en cada componente que renderiza el árbol lateral, duplicando la lógica de contar posts o renderizar enlaces.
2. La Solución Composite
// src/lib/CategoryNode.js
export class CategoryLeaf {
constructor(post) { this.post = post; }
countItems() { return 1; }
render() { return `<li><a href="${this.post.slug}">${this.post.meta.title}</a></li>`; }
}
export class CategoryComposite {
constructor(title) {
this.title = title;
this.children = [];
}
add(node) {
this.children.push(node);
return this;
}
countItems() {
// No distingue si el hijo es una hoja (post) u otra categoría anidada
return this.children.reduce((total, child) => total + child.countItems(), 0);
}
render() {
const items = this.children.map((c) => c.render()).join('');
return `<li>${this.title}<ul>${items}</ul></li>`;
}
}3. Uso en la barra lateral
const designPatterns = new CategoryComposite('Patrones de Diseño')
.add(new CategoryComposite('Creacionales').add(new CategoryLeaf(builderPost)))
.add(new CategoryLeaf(introPost));
designPatterns.countItems(); // funciona igual con 1 o 10 niveles de anidamiento4. Ventajas
- Un solo componente de navegación sirve para 1 o N niveles de subcategorías futuras.
- Contar posts totales (
countItems) no requiere recorrido manual niifpor tipo de nodo. - Extensible: añadir un tercer nivel de anidamiento no toca el código que ya consume
CategoryComposite.