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.
Sfida
FacileCostruiamo 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 enumPetTypecon i valoriPET_DOG,PET_CATePET_BIRD. Crea una struct basePetche contenga un puntatore a funzione perspeak(che accetta unconst Pet*e non restituisce nulla). Dichiara la funzione factorycreate_pet, che accetta unPetTypee restituisce unPet*, oltre a una funzionefree_petper la pulizia.pet.c: definisci tre struct concrete per gli animali,Dog,CateBird, ciascuna delle quali incorporaPetcome primo membro. Implementa una funzione speak per ogni tipo:- I cani stampano:
Woof! - I gatti stampano:
Meow! - Gli uccelli stampano:
Tweet!
create_pet: usa un'istruzione switch suPetTypeper chiamare il costruttore corretto e restituire il risultato comePet*. Per i tipi non validi, restituisciNULL. Implementafree_petper liberare la memoria allocata.- I cani stampano:
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 funzionespeakin modo polimorfico tramite il puntatore basePet*, 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;
}
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
1Basi di programmazione modulare
File di intestazioneGuardie di inclusioneFile sorgenteFunzioni staticheRipasso: calcolatrice modulare4Incapsulamento
Il concetto di puntatori opachiDefinire struct opacheGetter e setterLa convalida nei setterRiepilogo: scatola segreta2Oggetti e metodi
Le struct come oggettiIl puntatore 'Self'Correttezza constPuntatore o valoreMetodi di supportoRiepilogo: gestore di punti5Progetto: Conto bancario semplice
Configurazione del progettoImplementazione del conto8Polimorfismo
Puntatori a funzione nelle structSimulare i metodiIl concetto di interfacciaImplementare le interfacceIterazione polimorficaRiepilogo: Greeter11Pattern di progettazione in C
Pattern SingletonPattern FactoryPattern IteratorRiepilogo: Factory di Logger3Ciclo di vita degli oggetti
Pattern del costruttorePattern del distruttoreInizializzazione sullo stackCopia profondaRiepilogo: wrapper di stringhe6Ereditarietà tramite composizione
Incorporamento delle structLa regola del primo membroAccesso ai membri della classe baseUpcastingRiepilogo: gerarchia di forme9Progetto: Disegnatore di forme
Panoramica del progettoImplementazione del cerchioImplementazione del rettangoloUtilizzo polimorficoContenitore di formeEsercitati da solo: Compilatore C online