Menu
Coddy logo textTech

Pattern Factory

Fa parte della sezione Programmazione orientata agli oggetti del percorso C di Coddy. Lezione 55 di 61.

Il pattern Factory centralizza la creazione degli oggetti in un'unica funzione. Invece di disseminare malloc e il codice di inizializzazione nel programma, chiami una sola funzione che decide cosa creare e restituisce un oggetto pronto all'uso.

Questo modello è particolarmente potente se combinato con il polimorfismo. Una factory può restituire tipi concreti diversi tramite un puntatore alla classe base comune, nascondendo i dettagli della creazione al chiamante. Il chiamante chiede semplicemente «una forma» e la factory decide se creare un cerchio, un rettangolo o qualcos'altro.

Ecco un'implementazione tipica di una factory:

typedef enum {
    SHAPE_CIRCLE,
    SHAPE_RECTANGLE
} ShapeType;

Shape* create_shape(ShapeType type) {
    switch (type) {
        case SHAPE_CIRCLE:
            return (Shape*)create_circle(5.0);
        case SHAPE_RECTANGLE:
            return (Shape*)create_rectangle(4.0, 3.0);
        default:
            return NULL;
    }
}

La factory prende un identificatore (di solito un enum) e usa un'istruzione switch per determinare quale costruttore chiamare. Restituisce un Shape* indipendentemente dal tipo effettivamente creato. Chi la chiama non deve conoscere Circle o Rectangle. Lavora semplicemente con il tipo base:

Shape* s = create_shape(SHAPE_CIRCLE);
s->draw(s);  // chiamata polimorfica
free_shape(s);

Questo schema rende semplice aggiungere nuovi tipi: basta aggiungere un nuovo valore dell'enum e un nuovo caso nella factory. Il resto del codice rimane invariato.

challenge icon

Sfida

Facile

Costruiamo una fabbrica di animali domestici: un sistema che crea diversi tipi di animali domestici tramite un'unica funzione factory. Invece di spargere la logica di creazione in tutto il codice, la centralizzerai in un unico punto che decide quale tipo di animale creare in base a un identificatore di input.

Organizzerai il codice in tre file:

  • pet.h: definisci un enum PetType con i valori PET_DOG, PET_CAT e PET_BIRD. Crea una struct base Pet che contenga un puntatore a funzione per speak (che accetta un const Pet* e non restituisce nulla). Dichiara la funzione factory create_pet, che accetta un PetType e restituisce un Pet*, oltre a una funzione free_pet per la pulizia.
  • pet.c: definisci tre struct concrete per gli animali, Dog, Cat e Bird, ciascuna delle quali incorpora Pet come primo membro. Implementa una funzione speak per ogni tipo:
    • I cani stampano: Woof!
    • I gatti stampano: Meow!
    • Gli uccelli stampano: Tweet!
    Crea funzioni costruttrici per ogni tipo di animale, che allocano memoria e assegnano la funzione speak appropriata. Poi implementa la factory create_pet: usa un'istruzione switch su PetType per chiamare il costruttore corretto e restituire il risultato come Pet*. Per i tipi non validi, restituisci NULL. Implementa free_pet per liberare la memoria allocata.
  • main.c: leggi un intero che rappresenta il tipo di animale (0 per il cane, 1 per il gatto, 2 per l'uccello). Usa la factory per creare l'animale appropriato, chiama la sua funzione speak in modo polimorfico tramite il puntatore base Pet*, poi libera l'animale.

Il programma riceverà un input: un intero che indica quale animale creare.

Esempio di output quando l'input è 0:

Woof!

Esempio di output quando l'input è 1:

Meow!

Esempio di output quando l'input è 2:

Tweet!

Il bello del pattern Factory è che main.c non deve conoscere le struct Dog, Cat o Bird. Lavora soltanto con il tipo base Pet. Aggiungere in seguito un nuovo tipo di animale significa aggiungere un nuovo valore all'enum e un nuovo caso nella factory, senza modificare il codice che usa gli animali.

Provalo tu

#include <stdio.h>
#include "pet.h"

int main(void) {
    int type;
    scanf("%d", &type);
    
    // TODO: Usa la factory per creare l'animale domestico appropriato
    // Suggerimento: converti l'int in PetType
    
    // TODO: Chiama la funzione speak in modo polimorfico tramite il puntatore Pet*
    
    // TODO: Libera la memoria dell'animale domestico
    
    return 0;
}
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 C online