Pattern Factory
Fa parte della sezione Programmazione orientata agli oggetti del percorso Java di Coddy. Lezione 66 di 87.
Il Factory Pattern è un pattern di progettazione creazionale che delega la creazione degli oggetti a un metodo o a una classe separati. Invece di usare direttamente new nel tuo codice, chiedi a una factory di creare gli oggetti per te. È particolarmente utile quando hai più classi correlate che condividono un'interfaccia o una classe genitore.
Considera un sistema di notifiche che può inviare email, SMS o notifiche push. Senza una factory, il tuo codice dovrebbe conoscere ogni classe concreta:
// Senza Factory - il client deve conoscere tutte le classi concrete
Notification notification;
if (type.equals("email")) {
notification = new EmailNotification();
} else if (type.equals("sms")) {
notification = new SMSNotification();
}Con il Factory Pattern, centralizzi questa logica di creazione:
public interface Notification {
void send(String message);
}
public class EmailNotification implements Notification {
public void send(String message) {
System.out.println("Email: " + message);
}
}
public class SMSNotification implements Notification {
public void send(String message) {
System.out.println("SMS: " + message);
}
}
public class NotificationFactory {
public static Notification create(String type) {
if (type.equals("email")) {
return new EmailNotification();
} else if (type.equals("sms")) {
return new SMSNotification();
}
return null;
}
}Ora il codice client è più pulito e non dipende da classi concrete:
Notification notification = NotificationFactory.create("email");
notification.send("Hello!"); // Output: Email: Hello!Il vantaggio principale è che per aggiungere nuovi tipi di notifica è necessario aggiornare solo la factory: il codice client rimane invariato. Questo segue il principio di programmare verso un'interfaccia, rendendo il sistema più flessibile e facile da estendere.
Sfida
FacileCostruiamo un sistema per disegnare forme usando il Factory Pattern! Invece di creare direttamente oggetti forma in tutto il codice, centralizzerai la logica di creazione in una factory che produce diversi tipi di forme in base a un semplice identificatore stringa.
Organizzerai il codice in quattro file:
Shape.java: definisci un'interfaccia chiamataShapeche funge da contratto comune per tutte le forme. La tua interfaccia deve dichiarare un unico metododraw()che non restituisce nulla, ma stampa informazioni sulla forma disegnata.Shapes.java: crea tre classi che implementano la tua interfacciaShape:Circle- il suo metododraw()deve stampareDrawing a CircleRectangle- il suo metododraw()deve stampareDrawing a RectangleTriangle- il suo metododraw()deve stampareDrawing a TriangleShapeFactory.java: crea la classe factory che gestisce la creazione delle forme. La tuaShapeFactorydeve avere un metodo staticocreateShape(String type)che restituisce unaShape. In base al parametro type:- Se type è uguale a
"circle", restituisci una nuovaCircle - Se type è uguale a
"rectangle", restituisci una nuovaRectangle - Se type è uguale a
"triangle", restituisci una nuovaTriangle - Per qualsiasi altro valore, restituisci
null
- Se type è uguale a
Main.java: metti insieme il tuo sistema factory! Riceverai due input: due tipi di forme (entrambi String).Per ogni input, usa la tua
ShapeFactoryper creare la forma e memorizzarla in una variabileShape. Se la factory restituisce una forma valida (non null), chiama il suo metododraw(). Se restituisce null, stampaUnknown shape: [type]dove [type] è l'input fornito.Elabora entrambi gli input in ordine, ciascuno su una propria riga dell'output.
Riceverai due input in ordine: il primo tipo di forma (String) e il secondo tipo di forma (String).
Nota che la tua classe Main non usa mai direttamente new Circle() o new Rectangle(). Conosce solo l'interfaccia Shape e chiede alla factory di creare gli oggetti. Questa è la potenza del Factory Pattern: il codice client è disaccoppiato dalle classi concrete!
Provalo tu
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Leggi due tipi di forme
String type1 = scanner.nextLine();
String type2 = scanner.nextLine();
// TODO: Usa ShapeFactory per creare la prima forma
// Se la forma non è null, chiama draw()
// Se la forma è null, stampa "Unknown shape: [type]"
// TODO: Fai lo stesso per la seconda forma
}
}
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
1Fondamenti della programmazione a oggetti
File esterniIntroduzione alla programmazione a oggettiClassi e oggettiLa parola chiave thisMetodiCampi (attributi)Metodo costruttoreSovraccarico dei costruttoriRipasso - Calcolatrice semplice4Ereditarietà
Ereditarietà di base (extends)La parola chiave superSovrascrittura dei metodi (@Override)Concatenamento dei costruttoriLa classe ObjectEreditarietà singola e multilivelloPerché non esiste l'ereditarietà multipla delle classiRiepilogo: gerarchia dei dipendenti7Metodi speciali e classe Object
Metodo toString()equals() e hashCode()Metodo clone()compareTo() e ComparableInterfaccia ComparatorRiepilogo - Ordinamento personalizzato2Modificatori di accesso e incapsulamento
Panoramica dei livelli di accessoMetodi getter e setterNascondimento delle informazioniLa parola chiave finalRiepilogo - Gestore di conti bancari5Polimorfismo
Nozioni di base sull'overloading dei metodiOverride dei metodi (a runtime)Upcasting e downcastingL'operatore instanceofClassi e metodi astrattiRiepilogo - Calcolatore di forme8Concetti avanzati di OOP
Composizione vs ereditarietàAggregazione vs composizioneClassi interne, annidate e anonimeEnum e metodi degli EnumRecord (Java 16+)Classi sealed (Java 17+)11Modelli di progettazione Parte 1
Introduzione ai modelli di progettazionePattern SingletonPattern FactoryPattern BuilderPattern ObserverPattern Strategy3Proprietà di classe e membri statici
Variabili di istanza e staticheMetodi staticiBlocchi staticiCostanti (static final)Riepilogo - Contatore e utility6Interfacce e classi astratte
Introduzione alle interfacceImplementazione delle interfacceImplementazione di più interfacceMetodi default e static nelle interfacceClassi astratte e interfacce a confrontoInterfacce funzionaliRiepilogo: sistema di pagamento9Tipi generici
Introduzione ai tipi genericiClassi genericheMetodi genericiParametri di tipo con limitiCaratteri jolly (?, extends, super)Riepilogo - Contenitore generico12Modelli di progettazione – Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositePattern IteratorEsercitati da solo: Compilatore Java online