
I design pattern comportamentali giocano un ruolo fondamentale nel determinare come gli oggetti interagiscono tra loro. Questi pattern non si limitano a descrivere modelli di oggetti o classi, ma si concentrano anche sui modelli di comunicazione tra di loro e infatti permettono di gestire il flusso di controllo complesso, facilitando la collaborazione tra oggetti e migliorando la leggibilità e la manutenibilità del codice.
I pattern comportamentali si suddividono in due categorie principali: pattern di classe comportamentali e pattern di oggetti comportamentali. I pattern di classe utilizzano l’ereditarietà per distribuire il comportamento tra le classi, mentre i pattern di oggetti utilizzano la composizione di oggetti piuttosto che l’ereditarietà, promuovendo un accoppiamento lasco tra gli oggetti.
Procediamo ora con degli esempi partendo dai pattern di classe comportamentali.
Template Method
Il template method è uno dei pattern di classe comportamentali più semplici e comuni. Questo pattern definisce la struttura di un algoritmo in un metodo, delegando alcuni passaggi a sottoclassi e consente alle sottoclassi di ridefinire certi passaggi dell’algoritmo senza modificarne la struttura complessiva.
abstract class CaffeinaBeverage {
// Template method
final void preparaRicetta() {
bolleAcqua();
prepara();
versaInTazza();
if (aggiungiCondimentiNecessari()) {
aggiungiCondimenti();
}
}
abstract void prepara();
abstract void aggiungiCondimenti();
void bolleAcqua() {
System.out.println("Bollendo l'acqua");
}
void versaInTazza() {
System.out.println("Versando in tazza");
}
// Hook method
boolean aggiungiCondimentiNecessari() {
return true;
}
}
class Caffe extends CaffeinaBeverage {
void prepara() {
System.out.println("Preparando il caffè");
}
void aggiungiCondimenti() {
System.out.println("Aggiungendo zucchero e latte");
}
}
class Te extends CaffeinaBeverage {
void prepara() {
System.out.println("Preparando il tè");
}
void aggiungiCondimenti() {
System.out.println("Aggiungendo limone");
}
}
public class Main {
public static void main(String[] args) {
CaffeinaBeverage caffe = new Caffe();
caffe.preparaRicetta();
CaffeinaBeverage te = new Te();
te.preparaRicetta();
}
}
Code language: JavaScript (javascript)
Certo, ecco una spiegazione in 3 righe sul codice del Template Method:
Il template method definisce la sequenza di passaggi per preparare una bevanda, delegando alle sottoclassi Caffe
e Te
l’implementazione dei dettagli specifici. Questo approccio permette di riutilizzare il codice comune (come bollire l’acqua e versare in tazza) e personalizzare i passaggi variabili (come la preparazione e l’aggiunta di condimenti).
Passiamo ai pattern di oggetti comportamentali.
Strategy
Il pattern strategy consente di definire una famiglia di algoritmi, incapsularli e renderli intercambiabili. Questo pattern permette di selezionare l’algoritmo da utilizzare in modo dinamico a runtime.
interface StrategiaPagamento {
void paga(int importo);
}
class PagamentoCartaCredito implements StrategiaPagamento {
private String nome;
private String numeroCarta;
public PagamentoCartaCredito(String nome, String numeroCarta) {
this.nome = nome;
this.numeroCarta = numeroCarta;
}
@Override
public void paga(int importo) {
System.out.println(importo + "€ pagati con carta di credito.");
}
}
class PagamentoPayPal implements StrategiaPagamento {
private String email;
public PagamentoPayPal(String email) {
this.email = email;
}
@Override
public void paga(int importo) {
System.out.println(importo + "€ pagati con PayPal.");
}
}
class ContestoPagamento {
private StrategiaPagamento strategia;
public void setStrategia(StrategiaPagamento strategia) {
this.strategia = strategia;
}
public void eseguiPagamento(int importo) {
strategia.paga(importo);
}
}
public class Main {
public static void main(String[] args) {
ContestoPagamento contesto = new ContestoPagamento();
contesto.setStrategia(new PagamentoCartaCredito("Mario Rossi", "1234-5678-9012-3456"));
contesto.eseguiPagamento(100);
contesto.setStrategia(new PagamentoPayPal("mario.rossi@example.com"));
contesto.eseguiPagamento(200);
}
}
Code language: PHP (php)
L’interfaccia StrategiaPagamento
definisce il metodo paga
, mentre le classi PagamentoCartaCredito
e PagamentoPayPal
forniscono implementazioni specifiche di questo metodo. La classe ContestoPagamento
utilizza un’istanza di StrategiaPagamento
per eseguire il pagamento in base alla strategia selezionata. Nel metodo main
, vengono creati due contesti di pagamento con diverse strategie e viene eseguito il pagamento con l’importo specificato.
Conclusioni: semplicità ed importanza dei design pattern comportamentali
I design pattern comportamentali offrono soluzioni eleganti per gestire l’interazione complessa tra oggetti, migliorando la manutenibilità e la flessibilità del codice. La loro semplicità e capacità di risolvere problemi comuni nel design del software li rendono strumenti indispensabili per qualsiasi sviluppatore.
Questo ultimo articolo completa la saga dei design pattern, offrendo un’approfondita esplorazione dei pattern comportamentali.
Che tu sia un novizio o un esperto, spero che questa serie ti abbia ispirato e guidato verso l’eccellenza nello sviluppo software. Continua ad applicare queste conoscenze per creare soluzioni software innovative e di alta qualità!