Salta al contenuto principale

15 - Design Pattern Fondamentali

15 - Design Pattern Fondamentali: Design Pattern Fondamentali in Java I Design Pattern sono soluzioni riutilizzabili a problemi comuni.

Cosa ne pensi di questo articolo?

15 - Design Pattern Fondamentali
JavaFoto:Bibek ghoshPexels

In Breve

15 - Design Pattern Fondamentali: Design Pattern Fondamentali in Java I Design Pattern sono soluzioni riutilizzabili a problemi comuni.

Design Pattern Fondamentali in Java

I Design Pattern sono soluzioni riutilizzabili a problemi comuni. Conoscerli permette di scrivere codice più elegante, manutenibile e comunicare efficacemente con altri sviluppatori.

Pattern Trattati

  • Singleton - Istanza unica
  • Factory Method - Creazione delegata
  • Builder - Costruzione complessa
  • Strategy - Algoritmi intercambiabili
  • Observer - Notifiche di eventi

Singleton

Singleton Thread-Safe
// Singleton classico (thread-safe con enum)
public enum DatabaseConnection {
    INSTANCE;

    private Connection connection;

    DatabaseConnection() {
        // Inizializzazione connessione
    }

    public Connection getConnection() {
        return connection;
    }
}

// Uso
DatabaseConnection.INSTANCE.getConnection();

// Singleton con double-checked locking
public class ConfigurationManager {
    private static volatile ConfigurationManager instance;
    private Properties config;

    private ConfigurationManager() {
        config = new Properties();
        // Carica configurazione
    }

    public static ConfigurationManager getInstance() {
        if (instance == null) {
            synchronized (ConfigurationManager.class) {
                if (instance == null) {
                    instance = new ConfigurationManager();
                }
            }
        }
        return instance;
    }

    public String getProperty(String key) {
        return config.getProperty(key);
    }
}

Factory Method

Factory per Creazione Oggetti
// Interfaccia prodotto
interface Documento {
    void apri();
    void salva();
}

// Prodotti concreti
class DocumentoPdf implements Documento {
    public void apri() { System.out.println("Apri PDF"); }
    public void salva() { System.out.println("Salva PDF"); }
}

class DocumentoWord implements Documento {
    public void apri() { System.out.println("Apri Word"); }
    public void salva() { System.out.println("Salva Word"); }
}

// Factory
class DocumentoFactory {
    public static Documento crea(String tipo) {
        return switch (tipo.toUpperCase()) {
            case "PDF" -> new DocumentoPdf();
            case "WORD" -> new DocumentoWord();
            default -> throw new IllegalArgumentException("Tipo non supportato");
        };
    }
}

// Uso
Documento doc = DocumentoFactory.crea("PDF");
doc.apri();

Builder

Builder per Oggetti Complessi
public class Studente {
    private final String nome;
    private final String cognome;
    private final String email;
    private final int eta;
    private final String corso;

    private Studente(Builder builder) {
        this.nome = builder.nome;
        this.cognome = builder.cognome;
        this.email = builder.email;
        this.eta = builder.eta;
        this.corso = builder.corso;
    }

    // Getters...

    public static class Builder {
        private final String nome;  // Obbligatorio
        private final String cognome;  // Obbligatorio
        private String email;
        private int eta;
        private String corso;

        public Builder(String nome, String cognome) {
            this.nome = nome;
            this.cognome = cognome;
        }

        public Builder email(String email) {
            this.email = email;
            return this;
        }

        public Builder eta(int eta) {
            this.eta = eta;
            return this;
        }

        public Builder corso(String corso) {
            this.corso = corso;
            return this;
        }

        public Studente build() {
            return new Studente(this);
        }
    }
}

// Uso
Studente studente = new Studente.Builder("Mario", "Rossi")
    .email("mario@email.com")
    .eta(22)
    .corso("Informatica")
    .build();

Strategy

Strategy per Algoritmi Intercambiabili
// Interfaccia strategia
interface StrategiaOrdinamento {
    void ordina(int[] array);
}

// Strategie concrete
class BubbleSort implements StrategiaOrdinamento {
    public void ordina(int[] array) {
        // Implementazione bubble sort
        System.out.println("Ordinamento con Bubble Sort");
    }
}

class QuickSort implements StrategiaOrdinamento {
    public void ordina(int[] array) {
        // Implementazione quick sort
        System.out.println("Ordinamento con Quick Sort");
    }
}

// Contesto
class Ordinatore {
    private StrategiaOrdinamento strategia;

    public void setStrategia(StrategiaOrdinamento strategia) {
        this.strategia = strategia;
    }

    public void eseguiOrdinamento(int[] array) {
        strategia.ordina(array);
    }
}

// Uso
Ordinatore ordinatore = new Ordinatore();
ordinatore.setStrategia(new QuickSort());
ordinatore.eseguiOrdinamento(new int[]{5, 2, 8, 1});

Observer

Observer per Notifiche Eventi
import java.util.*;

// Interfaccia observer
interface Observer {
    void aggiorna(String messaggio);
}

// Subject (Observable)
class CanaleTelegramico {
    private List<Observer> iscritti = new ArrayList<>();
    private String ultimoMessaggio;

    public void iscrivi(Observer o) {
        iscritti.add(o);
    }

    public void disiscrivi(Observer o) {
        iscritti.remove(o);
    }

    public void pubblicaMessaggio(String messaggio) {
        this.ultimoMessaggio = messaggio;
        notificaTutti();
    }

    private void notificaTutti() {
        for (Observer o : iscritti) {
            o.aggiorna(ultimoMessaggio);
        }
    }
}

// Observer concreto
class Utente implements Observer {
    private String nome;

    public Utente(String nome) {
        this.nome = nome;
    }

    public void aggiorna(String messaggio) {
        System.out.println(nome + " ha ricevuto: " + messaggio);
    }
}

// Uso
CanaleTelegramico canale = new CanaleTelegramico();
canale.iscrivi(new Utente("Mario"));
canale.iscrivi(new Utente("Luigi"));
canale.pubblicaMessaggio("Nuovo articolo pubblicato!");

Quando Usare i Pattern

Guida alla Scelta

Pattern Quando Usarlo
Singleton Una sola istanza globale (config, connection pool)
Factory Creazione oggetti basata su parametri
Builder Oggetti con molti parametri opzionali
Strategy Comportamento che varia a runtime
Observer Notifiche di cambiamento stato

Domande frequenti

Quali sono le caratteristiche principali dei Design Pattern?

I Design Pattern sono soluzioni riutilizzabili a problemi comuni che consentono di scrivere codice più elegante, manutenibile e comunicare efficacemente con altri sviluppatori.

Qual è il vantaggio di utilizzare i Design Pattern in Java?

Utilizzare i Design Pattern in Java consente di creare codice più flessibile e facile da mantenere, riducendo al contempo la complessità del codice.

Come si classificano i diversi tipi di Design Pattern?

I Design Pattern possono essere classificati in base alla loro funzione, ad esempio Singleton, Factory Method, Builder, Strategy e Observer, ognuno con una specifica applicazione.

Quando è opportuno utilizzare un Design Pattern rispetto a un altro?

È opportuno utilizzare un Design Pattern quando si affrontano problemi comuni che richiedono soluzioni riutilizzabili, come ad esempio la gestione degli oggetti unici o la creazione di oggetti complessi.

Fonti e approfondimenti

Prova Questi Strumenti

Strumenti gratuiti correlati a questo argomento.

Commenti

Caricamento commenti...

Accedi per commentare

Discuti questo articolo nella community

Unisciti al gruppo Telegram per discutere con altri sviluppatori, fare domande e condividere le tue esperienze.

Ti è piaciuto questo articolo?

Esplora altri contenuti sul blog o scopri i miei progetti