Menu
Coddy logo textTech

Modello Composite

Fa parte della sezione Programmazione orientata agli oggetti del percorso PHP di Coddy. Lezione 80 di 91.

Il Composite Pattern è un pattern strutturale che consente di comporre oggetti in strutture ad albero e di lavorare con queste strutture come se fossero oggetti singoli. È perfetto per rappresentare gerarchie parte-tutto in cui vuoi trattare in modo uniforme gli oggetti singoli e i gruppi di oggetti.

Considera un file system. Una cartella può contenere file e altre cartelle.

Quando calcoli la dimensione totale, vuoi chiamare lo stesso metodo sia sui file sia sulle cartelle, e le cartelle dovrebbero sommare ricorsivamente i propri contenuti. Il Composite Pattern rende tutto questo semplice, fornendo la stessa interfaccia sia alle foglie (file) sia ai compositi (cartelle).

<?php
interface FileSystemItem {
    public function getName(): string;
    public function getSize(): int;
}

class File implements FileSystemItem {
    public function __construct(
        private string $name,
        private int $size
    ) {}
    
    public function getName(): string {
        return $this->name;
    }
    
    public function getSize(): int {
        return $this->size;
    }
}

class Folder implements FileSystemItem {
    private array $items = [];
    
    public function __construct(private string $name) {}
    
    public function getName(): string {
        return $this->name;
    }
    
    public function add(FileSystemItem $item): void {
        $this->items[] = $item;
    }
    
    public function getSize(): int {
        $total = 0;
        foreach ($this->items as $item) {
            $total += $item->getSize();
        }
        return $total;
    }
}

Ora puoi creare strutture ad albero e trattarle in modo uniforme:

<?php
$docs = new Folder("Documents");
$docs->add(new File("resume.pdf", 250));
$docs->add(new File("cover.docx", 50));

$images = new Folder("Images");
$images->add(new File("photo.jpg", 1500));

$root = new Folder("Root");
$root->add($docs);
$root->add($images);
$root->add(new File("readme.txt", 10));

echo $root->getSize();

Output:

1810

Il codice client chiama getSize() senza preoccuparsi se ha a che fare con un singolo file o con una struttura di cartelle profondamente annidata. Il pattern gestisce la ricorsione internamente, rendendo facile lavorare con gerarchie complesse.

challenge icon

Sfida

Facile

Creiamo un sistema di organigramma usando il Composite Pattern. Le aziende hanno una struttura gerarchica in cui i reparti possono contenere dipendenti e altri sottoreparti: una struttura ad albero perfetta per calcolare i totali in modo uniforme in tutta l’organizzazione.

Organizzerai il codice in quattro file:

  • OrganizationUnit.php: Definisci un’interfaccia OrganizationUnit che sarà implementata sia dai singoli dipendenti sia dai reparti. Dovrebbe avere due metodi: getName(): string e getSalary(): int. Questa interfaccia comune ti permette di trattare allo stesso modo i singoli dipendenti e i reparti interi quando calcoli i costi.
  • Employee.php: Includi l’interfaccia OrganizationUnit e crea una classe Employee che la implementa. Un dipendente è una foglia nell’albero dell’organizzazione. Ha un nome e uno stipendio, ma non può contenere altre unità. Usa la promozione delle proprietà del costruttore per accettare il nome e lo stipendio e implementa entrambi i metodi dell’interfaccia.
  • Department.php: Includi l’interfaccia OrganizationUnit e crea una classe Department che la implementa. Un reparto è un composito che può contenere sia dipendenti sia altri reparti. Il tuo reparto dovrebbe:
    • Accettare un nome nel costruttore
    • Implementare getName() per restituire il nome del reparto
    • Avere un metodo add(OrganizationUnit $unit): void per aggiungere dipendenti o sottoreparti
    • Implementare getSalary() per restituire lo stipendio totale di tutte le unità contenute (sommando ricorsivamente tutto ciò che si trova al loro interno)
  • main.php: Includi i file Employee e Department. Riceverai un input: una stringa JSON che rappresenta la struttura dell’organizzazione.

    Il JSON avrà questo formato:

    {"Engineering": [{"name": "Alice", "salary": 80000}, {"name": "Bob", "salary": 75000}], "Sales": [{"name": "Carol", "salary": 65000}]}

    Ogni chiave è il nome di un reparto e il relativo valore è un array di dipendenti con i rispettivi nomi e stipendi.

    Crea un Department radice chiamato "Company". Per ogni reparto nel JSON, crea un Department, aggiungi i suoi dipendenti e poi aggiungi quel reparto a Company. Infine, stampa lo stipendio totale dell’azienda in questo formato:

    Total Salary: [amount]

Il bello del Composite Pattern è che chiamando getSalary() sul reparto Company si calcola automaticamente la somma di tutti i reparti e i dipendenti annidati: il codice client non deve conoscere la struttura interna.

Provalo tu

<?php
require_once 'Employee.php';
require_once 'Department.php';

// Leggi l'input JSON
$input = trim(fgets(STDIN));
$data = (array)json_decode($input, true);

// TODO: Crea un Department radice chiamato "Company"

// TODO: Scorri ogni dipartimento nei dati JSON
// Per ogni dipartimento:
//   - Crea un nuovo oggetto Department
//   - Aggiungi ogni dipendente a quel dipartimento
//   - Aggiungi il dipartimento a Company

// TODO: Stampa lo stipendio totale nel formato: Total Salary: [amount]

?>
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore PHP online