logo

Metodo di fabbrica Design Pattern

Il modello di progettazione del metodo Factory è a modello di progettazione creativa che fornisce un'interfaccia per creare oggetti in una superclasse, consentendo alle sottoclassi di alterare il tipo di oggetti che verranno creati. Incapsula la logica di creazione degli oggetti in un metodo separato, promuovendo un accoppiamento libero tra il creatore e gli oggetti creati. Questo modello è particolarmente utile quando i tipi esatti di oggetti da creare possono variare o devono essere determinati in fase di esecuzione, consentendo flessibilità ed estensibilità nella creazione degli oggetti.

Tabella dei contenuti



Che cos'è il modello di progettazione del metodo Factory?

Il Factory Method Design Pattern è un modello di progettazione creazionale utilizzato nell'ingegneria del software per fornire un'interfaccia per la creazione di oggetti in una superclasse, consentendo al tempo stesso alle sottoclassi di alterare il tipo di oggetti che verranno creati. Incapsula la logica di creazione dell'oggetto in un metodo separato, astraendo il processo di istanziazione e promuovendo un accoppiamento libero tra il creatore e gli oggetti creati. Questo modello consente flessibilità, estensibilità e manutenibilità nel codice base consentendo alle sottoclassi di definire la propria implementazione del metodo factory per creare tipi specifici di oggetti.

mappa_non ordinata c++

Quando utilizzare il Factory Method Design Pattern?

Utilizza il modello di progettazione del metodo Factory:

  • Quando vuoi incapsulare la creazione di oggetti: Se si dispone di un processo di creazione di oggetti complesso o se il processo può variare in base alle condizioni, incapsulare questa logica in un metodo factory può semplificare il codice client e promuovere la riusabilità.
  • Quando vuoi disaccoppiare il codice client dalle classi concrete: L'utilizzo del Factory Method Pattern consente di creare oggetti tramite un'interfaccia o una classe astratta, estraendo i dettagli di implementazione specifici delle classi concrete dal codice client. Ciò favorisce un accoppiamento libero e semplifica la modifica o l'estensione del sistema senza influire sul codice client esistente.
  • Quando è necessario supportare più varianti di prodotto: Se la tua applicazione deve creare diverse varianti di un prodotto o se in futuro potrebbero essere introdotti nuovi tipi di prodotti, il Factory Method Pattern fornisce un modo flessibile per accogliere queste variazioni definendo metodi di fabbrica per ciascun tipo di prodotto.
  • Quando desideri supportare la personalizzazione o la configurazione: Le factory possono essere utilizzate per incapsulare la logica di configurazione, consentendo ai client di personalizzare il processo di creazione fornendo parametri o opzioni di configurazione al metodo factory.

Componenti del modello di progettazione del metodo Factory

1. Creatore

Questa è una classe astratta o un'interfaccia che dichiara il metodo factory. Il creatore in genere contiene un metodo che funge da factory per la creazione di oggetti. Può anche contenere altri metodi che funzionano con gli oggetti creati.

2. Creatore concreto

Le classi Concrete Creator sono sottoclassi del Creator che implementano il metodo factory per creare tipi specifici di oggetti. Ogni Concrete Creator è responsabile della creazione di un particolare prodotto.

3. Prodotto

Questa è l'interfaccia o la classe astratta per gli oggetti creati dal metodo factory. Il prodotto definisce l'interfaccia comune per tutti gli oggetti che il metodo factory può creare.

eol in Python

4. Prodotto concreto

Le classi Concrete Product sono gli oggetti reali creati dal metodo factory. Ogni classe Concrete Product implementa l'interfaccia Product o estende la classe astratta Product.

Esempio di modello di progettazione del metodo di fabbrica

Di seguito è riportata la dichiarazione del problema per comprendere il modello di progettazione del metodo Factory:

Consideriamo un'applicazione software che deve gestire la creazione di vari tipi di veicoli, ad esempio veicoli a due ruote, a tre ruote e a quattro ruote. Ogni tipo di veicolo ha le sue proprietà e comportamenti specifici.

1. Senza modello di progettazione del metodo di fabbrica

Giava
/*package whatever //do not write package name here */ import java.io.*; // Library classes abstract class Vehicle {  public abstract void printVehicle(); } class TwoWheeler extends Vehicle {  public void printVehicle() {  System.out.println('I am two wheeler');  } } class FourWheeler extends Vehicle {  public void printVehicle() {  System.out.println('I am four wheeler');  } } // Client (or user) class class Client {  private Vehicle pVehicle;  public Client(int type) {  if (type == 1) {  pVehicle = new TwoWheeler();  } else if (type == 2) {  pVehicle = new FourWheeler();  } else {  pVehicle = null;  }  }  public void cleanup() {  if (pVehicle != null) {  pVehicle = null;  }  }  public Vehicle getVehicle() {  return pVehicle;  } } // Driver program public class GFG {  public static void main(String[] args) {  Client pClient = new Client(1);  Vehicle pVehicle = pClient.getVehicle();  if (pVehicle != null) {  pVehicle.printVehicle();  }  pClient.cleanup();  } }>
Produzione
I am two wheeler>

Quali sono i problemi con il design di cui sopra?

Nella progettazione del codice sopra:

  • Accoppiamento stretto: La classe clienteClient>istanzia direttamente le classi concrete (TwoWheeler>EFourWheeler>) in base alla tipologia di input fornita in fase di costruzione. Ciò porta a uno stretto accoppiamento tra il client e le classi concrete, rendendo difficile la manutenzione e l'estensione del codice.
  • Violazione del principio di responsabilità unica (SRP): ILClient>La classe è responsabile non solo di determinare quale tipo di veicolo istanziare in base al tipo di input, ma anche di gestire il ciclo di vita dell'oggetto veicolo (ad esempio, la pulizia). Ciò viola il principio di responsabilità unica, secondo il quale una classe dovrebbe avere una sola ragione per cambiare.
  • Scalabilità limitata: L'aggiunta di un nuovo tipo di veicolo richiede la modifica delClient>classe, che viola il principio aperto-chiuso. Questo progetto non è scalabile perché non può accogliere nuovi tipi di veicoli senza modificare il codice esistente.

Come evitiamo il problema?

  • Definire l'interfaccia di fabbrica: Creare unVehicleFactory>interfaccia o classe astratta con un metodo per creare veicoli.
  • Implementare fabbriche di calcestruzzo: Implementare classi di fabbrica di calcestruzzo (TwoWheelerFactory>EFourWheelerFactory>) che implementano ilVehicleFactory>interfaccia e fornire metodi per creare istanze di tipi specifici di veicoli.
  • Cliente del refactoring: Modifica ilClient>classe per accettare aVehicleFactory>esempio invece di istanziare direttamente i veicoli. Il cliente richiederà un veicolo dalla fabbrica, eliminando la necessità di una logica condizionale basata sulla tipologia di veicolo.
  • Maggiore flessibilità: Con questo approccio, aggiungere nuovi tipi di veicoli è semplice come creare una nuova classe di fabbrica per il nuovo tipo di veicolo senza modificare il codice cliente esistente.

2. Con modello di progettazione del metodo di fabbrica

Suddividiamo il codice in codice saggio per componenti:

FactoryMethodDesignPattern

1. Interfaccia del prodotto

Giava
// Product interface representing a vehicle public abstract class Vehicle {  public abstract void printVehicle(); }>

2. Prodotti in calcestruzzo

Giava
// Concrete product classes representing different types of vehicles public class TwoWheeler extends Vehicle {  public void printVehicle() {  System.out.println('I am two wheeler');  } } public class FourWheeler extends Vehicle {  public void printVehicle() {  System.out.println('I am four wheeler');  } }>

3. Interfaccia creatore (interfaccia di fabbrica)

Giava
// Factory interface defining the factory method public interface VehicleFactory {  Vehicle createVehicle(); }>

4. Creatori di cemento (fabbriche di cemento)

Giava
// Concrete factory class for TwoWheeler public class TwoWheelerFactory implements VehicleFactory {  public Vehicle createVehicle() {  return new TwoWheeler();  } } // Concrete factory class for FourWheeler public class FourWheelerFactory implements VehicleFactory {  public Vehicle createVehicle() {  return new FourWheeler();  } }>

Codice completo di questo esempio:

Giava
// Library classes abstract class Vehicle {  public abstract void printVehicle(); } class TwoWheeler extends Vehicle {  public void printVehicle() {  System.out.println('I am two wheeler');  } } class FourWheeler extends Vehicle {  public void printVehicle() {  System.out.println('I am four wheeler');  } } // Factory Interface interface VehicleFactory {  Vehicle createVehicle(); } // Concrete Factory for TwoWheeler class TwoWheelerFactory implements VehicleFactory {  public Vehicle createVehicle() {  return new TwoWheeler();  } } // Concrete Factory for FourWheeler class FourWheelerFactory implements VehicleFactory {  public Vehicle createVehicle() {  return new FourWheeler();  } } // Client class class Client {  private Vehicle pVehicle;  public Client(VehicleFactory factory) {  pVehicle = factory.createVehicle();  }  public Vehicle getVehicle() {  return pVehicle;  } } // Driver program public class GFG {  public static void main(String[] args) {  VehicleFactory twoWheelerFactory = new TwoWheelerFactory();  Client twoWheelerClient = new Client(twoWheelerFactory);  Vehicle twoWheeler = twoWheelerClient.getVehicle();  twoWheeler.printVehicle();  VehicleFactory fourWheelerFactory = new FourWheelerFactory();  Client fourWheelerClient = new Client(fourWheelerFactory);  Vehicle fourWheeler = fourWheelerClient.getVehicle();  fourWheeler.printVehicle();  } }>
Produzione
I am two wheeler I am four wheeler>

Nel codice sopra:

Java confronta la stringa
  • Vehicle> funge da interfaccia del prodotto, definendo il metodo comune printVehicle()> che tutti i prodotti concreti devono attuare.
  • TwoWheeler> E FourWheeler> sono classi di prodotti concreti che rappresentano diversi tipi di veicoli, implementando il printVehicle()> metodo.
  • VehicleFactory> funge da interfaccia Creator (Factory Interface) con un metodo createVehicle()> che rappresenta il metodo di fabbrica.
  • TwoWheelerFactory> E FourWheelerFactory> sono classi di creatori concreti (Concrete Factories) che implementano il VehicleFactory> interfaccia per creare istanze di tipi specifici di veicoli.

Casi d'uso del modello di progettazione del metodo Factory

Ecco alcune applicazioni comuni del modello Factory Method Design:

  • Strutture creazionali:
    • JDBC (Java Database Connectivity) utilizza ampiamente le factory per creare connessioni, istruzioni e set di risultati. I framework di inserimento delle dipendenze come Spring e Guice fanno molto affidamento sulle fabbriche per creare e gestire i bean.
  • Kit di strumenti GUI:
    • Swing e JavaFX utilizzano le factory per creare componenti dell'interfaccia utente come pulsanti, campi di testo ed etichette, consentendo personalizzazione e flessibilità nella progettazione dell'interfaccia utente.
  • Framework di registrazione:
    • I framework di registrazione come Log4j e Logback utilizzano fabbriche per creare logger con diverse configurazioni, consentendo il controllo sui livelli di registrazione e sulle destinazioni di output.
  • Serializzazione e deserializzazione:
    • I framework di serializzazione degli oggetti spesso utilizzano factory per creare oggetti da dati serializzati, supportando diversi formati di serializzazione e versioni.
  • Sistemi di plugin:
    • I sistemi basati su plugin spesso utilizzano factory per caricare e creare istanze di plugin in modo dinamico, consentendo estensibilità e personalizzazione.
  • Sviluppo del gioco:
    • I motori di gioco utilizzano spesso le fabbriche per creare diversi tipi di oggetti, personaggi e livelli di gioco, promuovendo l'organizzazione e la flessibilità del codice.
  • Sviluppo web:
    • I framework web a volte utilizzano factory per creare componenti di visualizzazione, controller e servizi, consentendo modularità e testabilità nelle applicazioni web.

Vantaggi del modello di progettazione del metodo Factory

I vantaggi del Factory Method Design Pattern sono:

stampa javascript
  • Disaccoppiamento: Separa la logica di creazione degli oggetti dal codice client che utilizza tali oggetti. Ciò rende il codice più flessibile e gestibile perché le modifiche al processo di creazione non richiedono modifiche al codice client.
  • Estensibilità: È facile introdurre nuovi tipi di prodotto senza modificare il codice cliente. Devi semplicemente creare una nuova sottoclasse Concrete Creator e implementare il metodo factory per produrre il nuovo prodotto.
  • Testabilità: Semplifica i test unitari consentendoti di simulare o bloccare la creazione del prodotto durante i test. È possibile testare separatamente implementazioni di prodotti diversi senza fare affidamento sulla creazione effettiva dell'oggetto.
  • Riutilizzabilità del codice: Il metodo factory può essere riutilizzato in diverse parti dell'applicazione in cui è necessaria la creazione di oggetti. Ciò promuove la centralizzazione e il riutilizzo della logica di creazione degli oggetti.
  • Incapsulamento: Nasconde le classi di prodotto concrete dal codice client, rendendo il codice meno dipendente da implementazioni specifiche. Ciò migliora la manutenibilità e riduce l'accoppiamento.

Svantaggi del modello di progettazione del metodo Factory

Gli svantaggi del Factory Method Design Pattern sono:

  • Maggiore complessità: Introduce classi e interfacce aggiuntive, aggiungendo un livello di astrazione che può rendere il codice più complesso da comprendere e mantenere, soprattutto per chi non ha familiarità con il pattern.
  • In testa: L'uso del polimorfismo e del legame dinamico può avere un leggero impatto sulle prestazioni, sebbene questo sia spesso trascurabile nella maggior parte delle applicazioni.
  • Stretto accoppiamento all’interno delle gerarchie di prodotti: I Creatori di Calcestruzzo sono ancora strettamente legati ai loro corrispondenti Prodotti di Calcestruzzo. Le modifiche all'uno spesso richiedono modifiche all'altro.
  • Dipendenza dalle sottoclassi di calcestruzzo: Il codice client dipende ancora dalla classe astratta Creator, richiedendo la conoscenza delle sue sottoclassi concrete per effettuare chiamate corrette al metodo factory.
  • Potenziale di uso eccessivo: È importante utilizzare con giudizio il modello Factory Method per evitare di sovraccaricare l'applicazione. La creazione semplice di oggetti può spesso essere gestita direttamente senza la necessità di una factory.
  • Sfide di test: Testare la logica stessa della fabbrica può essere più complesso.