Menu
Coddy logo textTech

Costruttori factory

Fa parte della sezione Programmazione orientata agli oggetti del percorso Dart di Coddy. Lezione 14 di 110.

Un costruttore factory è un costruttore speciale che non crea sempre una nuova istanza. A differenza dei costruttori normali, un costruttore factory può restituire un'istanza esistente, un sottotipo o persino null (se nullable). Lo dichiari usando la parola chiave factory.

class Logger {
  static final Logger _instance = Logger._internal();
  
  // Costruttore con nome privato
  Logger._internal();
  
  // Costruttore factory
  factory Logger() {
    return _instance;
  }
}

Logger log1 = Logger();
Logger log2 = Logger();
print(identical(log1, log2)); // true

In questo esempio, il costruttore factory restituisce sempre la stessa istanza. Indipendentemente da quante volte chiami Logger(), ottieni lo stesso oggetto. Questo schema viene comunemente usato per implementare i singleton.

I costruttori factory differiscono dai costruttori normali per un aspetto fondamentale: non hanno accesso a this perché potrebbero non creare affatto una nuova istanza. Devono invece restituire esplicitamente un oggetto:

class Shape {
  factory Shape(String type) {
    if (type == 'circle') return Circle();
    if (type == 'square') return Square();
    return Rectangle();
  }
}

class Circle extends Shape { Circle() : super._(); }
class Square extends Shape { Square() : super._(); }
class Rectangle extends Shape { Rectangle() : super._(); }

I costruttori factory sono utili quando hai bisogno di controllare la creazione delle istanze, ad esempio per restituire oggetti memorizzati nella cache, implementare pool di oggetti o decidere quale sottotipo istanziare in base ai parametri di input.

challenge icon

Sfida

Facile

Creiamo un sistema di notifiche che utilizza costruttori factory per creare diversi tipi di notifiche in base a una semplice stringa in input.

Creerai due file per organizzare il codice:

  • notification.dart: definisci una classe Notification che funge da base per tutti i tipi di notifica. La classe deve avere:
    • Un campo String message
    • Un costruttore con nome privato Notification._internal che inizializza il messaggio
    • Un costruttore factory Notification(String type, String message) che restituisce diversi sottotipi di notifica in base al parametro type:
      • Se type è 'email', restituisci un EmailNotification
      • Se type è 'sms', restituisci un SMSNotification
      • Altrimenti, restituisci un PushNotification
    • Un metodo send() che stampa Sending: [message]

Nello stesso file, crea tre sottoclassi che estendono Notification:

  • EmailNotification: esegui l’override di send() per stampare Email: [message]
  • SMSNotification: esegui l’override di send() per stampare SMS: [message]
  • PushNotification: esegui l’override di send() per stampare Push: [message]

Ogni sottoclasse deve avere un costruttore che riceve un message e lo passa alla classe genitore usando super._internal(message).

  • main.dart: importa la classe di notifica e crea tre notifiche usando il costruttore factory:
    • Una notifica email con il messaggio 'Welcome!'
    • Una notifica SMS con il messaggio 'Your code is 1234'
    • Una notifica push con il messaggio 'New update available'
    Chiama send() su ogni notifica nell’ordine indicato sopra.

Output previsto:

Email: Welcome!
SMS: Your code is 1234
Push: New update available

Provalo tu

import 'notification.dart';

void main() {
  // TODO: Crea una notifica email con il messaggio 'Welcome!'
  
  // TODO: Crea una notifica SMS con il messaggio 'Your code is 1234'
  
  // TODO: Crea una notifica push con il messaggio 'New update available'
  
  // TODO: Chiama send() su ogni notifica nell'ordine previsto
}
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 Dart online