Menu
Coddy logo textTech

Introduzione ai modelli di progettazione

Fa parte della sezione Programmazione orientata agli oggetti del percorso GO di Coddy. Lezione 85 di 107.

I pattern di progettazione sono soluzioni riutilizzabili a problemi comuni che si presentano nella progettazione del software. Non sono codice da copiare direttamente, ma piuttosto modelli che guidano il modo in cui strutturi i tuoi tipi e le loro interazioni per risolvere sfide specifiche.

I pattern di progettazione sono generalmente raggruppati in tre categorie:

CategoriaScopoEsempi
CreazionaliMeccanismi di creazione degli oggettiSingleton, Factory, Builder
StrutturaliComposizione di tipi in strutture più grandiAdapter, Decorator, Composite
ComportamentaliComunicazione tra oggettiObserver, Strategy, Command

In Go, i pattern di progettazione hanno un aspetto diverso rispetto ai linguaggi OOP tradizionali.

Senza classi o ereditarietà, Go implementa i pattern usando interfacce, incorporamento di struct e composizione. Per esempio, dove Java potrebbe usare una classe astratta, Go usa un'interfaccia. Dove C++ potrebbe usare l'ereditarietà, Go usa l'incorporamento.

Imparare i pattern ti aiuta a riconoscere i problemi comuni e a comunicare efficacemente le soluzioni agli altri sviluppatori. Quando qualcuno dice «usa qui il pattern Strategy», tutto il team capisce l’approccio senza bisogno di lunghe spiegazioni.

Nelle prossime lezioni implementerai diversi pattern fondamentali in Go, iniziando con pattern creazionali come Singleton e Factory, per poi passare a pattern comportamentali come Observer e Strategy.

challenge icon

Sfida

Facile

Costruiamo un semplice sistema di notifiche che mostri come i pattern di progettazione aiutano a organizzare il codice! Creerai una struttura che in futuro potrà essere facilmente estesa con pattern come Observer o Strategy, ma per ora concentrati sulla creazione di interfacce e tipi ben organizzati, seguendo i principi OOP.

Organizzerai il codice in tre file:

  • notifier.go: Definisci l'interfaccia principale e i tipi per il tuo sistema di notifiche.

    Crea un'interfaccia Notifier con un solo metodo Send(message string) string che restituisce un messaggio di conferma.

    Implementa due tipi concreti di notificatore:

    • EmailNotifier con un campo Address. Il suo metodo Send restituisce Email to [address]: [message]
    • SMSNotifier con un campo PhoneNumber. Il suo metodo Send restituisce SMS to [phone]: [message]
  • dispatcher.go: Crea un dispatcher che funzioni con qualsiasi notificatore tramite l'interfaccia.

    Crea una struct NotificationDispatcher che contenga una slice di interfacce Notifier. Aggiungi questi metodi:

    • AddNotifier(n Notifier) per registrare un notificatore
    • Broadcast(message string) []string che invia il messaggio tramite tutti i notificatori registrati e restituisce una slice di tutte le stringhe di conferma

    Crea anche un costruttore NewNotificationDispatcher() che restituisca un dispatcher inizializzato.

  • main.go: Configura i notificatori e trasmetti i messaggi.

    Leggi il numero di notificatori da creare. Per ciascun notificatore, leggi il suo tipo (email o sms) e la sua destinazione (indirizzo o numero di telefono). Aggiungili a un dispatcher.

    Poi leggi un messaggio da trasmettere. Invialo tramite tutti i notificatori e stampa ogni conferma su una riga separata.

Verranno forniti i seguenti input:

  • Riga 1: numero di notificatori
  • Per ogni notificatore: tipo (email o sms), poi la destinazione
  • Riga finale: messaggio da trasmettere

Per esempio, dato:

3
email
alice@example.com
sms
555-1234
email
bob@example.com
Server maintenance at midnight

Il tuo output dovrebbe essere:

Email to alice@example.com: Server maintenance at midnight
SMS to 555-1234: Server maintenance at midnight
Email to bob@example.com: Server maintenance at midnight

E dato:

2
sms
555-9999
sms
555-0000
Meeting canceled

Il tuo output dovrebbe essere:

SMS to 555-9999: Meeting canceled
SMS to 555-0000: Meeting canceled

Questa struttura mostra come le interfacce consentano di creare progetti flessibili ed estensibili. Il dispatcher non conosce i tipi specifici di notificatore. Sa solo che possono Send. Questa è la base su cui si fondano pattern come Observer e Strategy!

Provalo tu

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin)

	// Leggi il numero di notificatori
	countStr, _ := reader.ReadString('\n')
	count, _ := strconv.Atoi(strings.TrimSpace(countStr))

	// Crea un nuovo dispatcher
	dispatcher := NewNotificationDispatcher()

	// Leggi ogni notificatore e aggiungilo al dispatcher
	for i := 0; i < count; i++ {
		notifierType, _ := reader.ReadString('\n')
		notifierType = strings.TrimSpace(notifierType)

		destination, _ := reader.ReadString('\n')
		destination = strings.TrimSpace(destination)

		// TODO: Crea il notificatore appropriato in base al tipo
		// e aggiungilo al dispatcher
		// Suggerimento: controlla se notifierType è "email" o "sms"

	}

	// Leggi il messaggio da inviare a tutti
	message, _ := reader.ReadString('\n')
	message = strings.TrimSpace(message)

	// TODO: Invia il messaggio a tutti e stampa ogni conferma

}
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 Go online