Ce este
Șablonul Composite tratează lucrurile individuale și grupurile de lucruri prin aceeași interfață. Un fișier are o dimensiune; un folder plin de fișiere (și de foldere) are și el o dimensiune — așa că ambele implementează size(), iar codul care adună dimensiunile nu întreabă niciodată ce anume ține.
Compozitele formează în mod natural arbori: grupurile conțin frunze și alte grupuri, la orice adâncime.
Exemplu: fișiere și foldere
Interfața Item are o singură metodă. Un FileItem răspunde cu propria dimensiune; un Folder întreabă tot ce se află înăuntru și adună — recursivitatea apare de la sine.
O singură interfață pentru frunză și pentru grup
root.size() parcurge întregul arbore fără nicio verificare de tip: folderului nu îi pasă dacă un element este un fișier de 4 KB sau un alt folder care ascunde încă zece. Folderul docs răspunde 10, iar root răspunde 12 — propriul fișier de 2 KB plus tot ce se află în docs.
Ieșire: program TypeScript și rezultatul capturat
interface Item {
size(): number
}
// O frunză: știe pur și simplu propria dimensiune.
class FileItem implements Item {
name: string
private kb: number
constructor(name: string, kb: number) {
this.name = name
this.kb = kb
}
size(): number {
return this.kb
}
}
class Folder implements Item {
name: string
private items: Item[]
constructor(name: string, items: Item[]) {
this.name = name
this.items = items
}
// Dimensiunea unui folder este suma a tot ce se află înăuntru — fișiere sau foldere.
size(): number {
let total = 0
for (const item of this.items) {
total += item.size()
}
return total
}
}
const docs = new Folder("docs", [
new FileItem("notes.txt", 4),
new FileItem("plan.md", 6)
])
const root = new Folder("root", [
new FileItem("readme.md", 2),
docs
])
console.log("dimensiune docs:", docs.size(), "KB")
console.log("dimensiune root:", root.size(), "KB")
Când să îl folosești
Folosește-l pentru date în formă de arbore, unde grupurile și elementele individuale răspund la aceleași întrebări — sisteme de fișiere, meniuri cu submeniuri, aranjamente de interfață, organigrame.
Evită-l pentru liste plate. Un tablou cu o buclă nu are nevoie de niciun șablon.
Avantaje și dezavantaje
Avantaje: codul client rămâne simplu și plat; arborii de orice adâncime vin gratuit; clasele noi de frunze sau de grupuri se conectează la aceeași interfață.
Dezavantaje: interfața comună poate impune metode nepotrivite pe frunze (ce înseamnă „adaugă un copil” pentru un fișier?); compozitele foarte generale devin greu de ținut sub control.