# FizzBuzz in PHP: soluzione base e con i design pattern

> Cos'è il FizzBuzz, perché viene usato nei colloqui e come risolverlo in PHP: la soluzione base e le versioni con Strategy, Template Method e Chain of Responsibility.

- URL: https://mautoblog.com/posts/soluzioni-fizz-buzz/
- Lingua: it
- Pubblicato: 2024-09-28
- Aggiornato: 2026-10-16
- Autore: Matteo
- Categorie: Sviluppo Software
- Tags: Architettura Software, Testing, Machine Learning, Best Practices, PHP

---
Il FizzBuzz è un test semplice e comune nei colloqui di lavoro per sviluppatori, progettato per valutare la capacità di scrivere codice pulito e di implementare logica condizionale di base.

### Descrizione del problema:
Il test chiede di stampare i numeri da 1 a un limite definito (solitamente 100), con le seguenti regole:

- Se un numero è divisibile per 3, stampare "**Fizz**" al posto del numero.
- Se un numero è divisibile per 5, stampare "**Buzz**" al posto del numero.
- Se un numero è divisibile sia per 3 che per 5, stampare "**FizzBuzz**".
- Per tutti gli altri numeri, stampare il numero stesso.

### A cosa serve?
Il FizzBuzz non è complesso, ma permette ai reclutatori di valutare la capacità del candidato di:

- Gestire la logica condizionale.
- Lavorare con cicli e operazioni base su numeri.
- Scrivere codice chiaro, leggibile e senza errori di sintassi.
- Dimostrare velocemente le competenze di base in un linguaggio di programmazione.

### Esempio di output:
```bash
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
```

Il problema **FizzBuzz** può essere risolto in diversi modi, sia utilizzando una logica di base che applicando diversi design patterns.
Vediamo un po' di soluzioni.

### Soluzione Base
Questa è la soluzione di base, in cui si utilizza un semplice controllo condizionale:
```php
function fizzBuzz($n) {
    for ($i = 1; $i <= 100; $i++) {
        if ($i % 3 == 0 && $i % 5 == 0) {
            echo "FizzBuzz\n";
        } elseif ($i % 3 == 0) {
            echo "Fizz\n";
        } elseif ($i % 5 == 0) {
            echo "Buzz\n";
        } else {
            echo "$i\n";
        }
    }
}
```

### Soluzione con lo Strategy Pattern
Qui possiamo usare il [Strategy Pattern](/posts/design-patterns/strategy/) per gestire le diverse condizioni di Fizz, Buzz e FizzBuzz.
Ogni strategia definisce il comportamento da applicare a numeri specifici.

```php
// Interfaccia per le strategie
interface FizzBuzzStrategy {
    public function apply($number);
}

// Strategia per FizzBuzz
class FizzBuzz implements FizzBuzzStrategy {
    public function apply($number) {
        if ($number % 3 == 0 && $number % 5 == 0) {
            return "FizzBuzz";
        }
        return null;
    }
}

// Strategia per Fizz
class Fizz implements FizzBuzzStrategy {
    public function apply($number) {
        if ($number % 3 == 0) {
            return "Fizz";
        }
        return null;
    }
}

// Strategia per Buzz
class Buzz implements FizzBuzzStrategy {
    public function apply($number) {
        if ($number % 5 == 0) {
            return "Buzz";
        }
        return null;
    }
}

// Classe che gestisce il contesto
class FizzBuzzContext {
    private $strategies;

    public function __construct() {
        $this->strategies = [];
    }

    public function addStrategy(FizzBuzzStrategy $strategy) {
        $this->strategies[] = $strategy;
    }

    public function process($number) {
        foreach ($this->strategies as $strategy) {
            $result = $strategy->apply($number);
            if ($result !== null) {
                return $result;
            }
        }
        return $number;
    }
}

// Esempio d'uso
$fizzBuzzContext = new FizzBuzzContext();
$fizzBuzzContext->addStrategy(new FizzBuzz());
$fizzBuzzContext->addStrategy(new Fizz());
$fizzBuzzContext->addStrategy(new Buzz());

for ($i = 1; $i <= 100; $i++) {
    echo $fizzBuzzContext->process($i) . "\n";
}
```

### Soluzione con il Chain of Responsibility Pattern
Usiamo ora invece il [Chain of Responsibility Pattern](/posts/design-patterns/chain-of-responsibility/) per creare una catena di controllo che passa il numero attraverso diverse responsabilità (Fizz, Buzz, FizzBuzz).
```php
// Interfaccia per il nodo della catena
abstract class FizzBuzzHandler {
    protected $nextHandler;

    public function setNext(FizzBuzzHandler $handler) {
        $this->nextHandler = $handler;
    }

    abstract public function handle($number);
}

// Handler per FizzBuzz
class FizzBuzzHandlerConcrete extends FizzBuzzHandler {
    public function handle($number) {
        if ($number % 3 == 0 && $number % 5 == 0) {
            return "FizzBuzz";
        } else {
            return $this->nextHandler ? $this->nextHandler->handle($number) : $number;
        }
    }
}

// Handler per Fizz
class FizzHandler extends FizzBuzzHandler {
    public function handle($number) {
        if ($number % 3 == 0) {
            return "Fizz";
        } else {
            return $this->nextHandler ? $this->nextHandler->handle($number) : $number;
        }
    }
}

// Handler per Buzz
class BuzzHandler extends FizzBuzzHandler {
    public function handle($number) {
        if ($number % 5 == 0) {
            return "Buzz";
        } else {
            return $this->nextHandler ? $this->nextHandler->handle($number) : $number;
        }
    }
}

// Esempio d'uso
$fizzBuzzHandler = new FizzBuzzHandlerConcrete();
$fizzHandler = new FizzHandler();
$buzzHandler = new BuzzHandler();

$fizzBuzzHandler->setNext($fizzHandler);
$fizzHandler->setNext($buzzHandler);

for ($i = 1; $i <= 100; $i++) {
    echo $fizzBuzzHandler->handle($i) . "\n";
}
```

### Soluzione con il Template Method Pattern
Ultima soluzione utilizzando Il **[Template Method Pattern](/posts/design-patterns/template-method/)**, che permette di definire una struttura generale dell'algoritmo e lasciare alle sottoclassi il compito di implementare i dettagli (Fizz, Buzz, FizzBuzz).
```php
// Classe astratta con il template method
abstract class FizzBuzzTemplate {
    public function process($number) {
        if ($this->isFizzBuzz($number)) {
            return "FizzBuzz";
        } elseif ($this->isFizz($number)) {
            return "Fizz";
        } elseif ($this->isBuzz($number)) {
            return "Buzz";
        } else {
            return $number;
        }
    }

    protected abstract function isFizzBuzz($number);
    protected abstract function isFizz($number);
    protected abstract function isBuzz($number);
}

// Implementazione concreta
class FizzBuzzGame extends FizzBuzzTemplate {
    protected function isFizzBuzz($number) {
        return $number % 3 == 0 && $number % 5 == 0;
    }

    protected function isFizz($number) {
        return $number % 3 == 0;
    }

    protected function isBuzz($number) {
        return $number % 5 == 0;
    }
}

// Esempio d'uso
$fizzBuzzGame = new FizzBuzzGame();

for ($i = 1; $i <= 100; $i++) {
    echo $fizzBuzzGame->process($i) . "\n";
}
```

## Conclusione
In ciascuno di questi esempi, il problema **FizzBuzz** è stato risolto in modi diversi, mostrando come lo stesso problema possa essere affrontato utilizzando vari design patterns.
La soluzione base è semplice e diretta, ma l'utilizzo di design patterns come **Strategy**, **Chain of Responsibility** o **Template Method** fornisce un approccio più strutturato, modulare e facilmente estendibile, specialmente per applicazioni più complesse.

