Modello Factory
Fa parte della sezione Programmazione orientata agli oggetti del percorso GO di Coddy. Lezione 87 di 107.
Il pattern Factory delega la creazione degli oggetti a una funzione o a un metodo separato, consentendoti di creare istanze senza esporre la logica di creazione. A differenza del Singleton, che controlla il numero di istanze, Factory si concentra sulla creazione flessibile di oggetti in base ai parametri di input.
In Go, una factory è in genere una funzione che restituisce un tipo di interfaccia, consentendoti di creare diversi tipi concreti tramite un'API unificata:
type Notifier interface {
Send(message string) string
}
type EmailNotifier struct{}
type SMSNotifier struct{}
func (e EmailNotifier) Send(message string) string {
return "Email: " + message
}
func (s SMSNotifier) Send(message string) string {
return "SMS: " + message
}
func NewNotifier(notifierType string) Notifier {
switch notifierType {
case "email":
return EmailNotifier{}
case "sms":
return SMSNotifier{}
default:
return EmailNotifier{}
}
}La funzione factory NewNotifier incapsula la decisione su quale tipo concreto creare. Il codice client lavora solo con l’interfaccia Notifier, senza conoscere l’implementazione specifica:
notifier := NewNotifier("sms")
result := notifier.Send("Hello!") // "SMS: Hello!"Questo schema è particolarmente utile quando devi creare oggetti in base a condizioni di runtime, vuoi centralizzare una logica di inizializzazione complessa o hai bisogno di aggiungere facilmente nuovi tipi senza modificare il codice client. Ti basta aggiungere una nuova struct che implementa l’interfaccia e aggiornare la funzione factory.
Sfida
FacileCostruiamo un sistema di conversione di documenti usando il modello Factory! Creerai una factory che produce diversi convertitori di documenti in base al formato di destinazione, consentendo al codice client di lavorare con qualsiasi convertitore tramite un'interfaccia unificata.
Organizzerai il codice in due file:
converter.go: definisci l'interfaccia del convertitore e le implementazioni concrete.Crea un'interfaccia
Convertercon un metodoConvert(content string) stringche accetta il contenuto del documento e restituisce il risultato convertito.Implementa tre tipi di convertitore:
PDFConverter: il suo metodoConvertrestituiscePDF: [content]HTMLConverter: il suo metodoConvertrestituisceHTML: <p>[content]</p>MarkdownConverter: il suo metodoConvertrestituisceMD: # [content]
Crea una funzione factory
NewConverter(format string) Converterche restituisce il convertitore appropriato in base alla stringa del formato (pdf,htmlomarkdown). Per qualsiasi formato non riconosciuto, restituisci unPDFConvertercome valore predefinito.main.go: usa la tua factory per creare convertitori ed elaborare documenti.Leggi un tipo di formato e il contenuto di un documento. Usa la factory per creare il convertitore appropriato, quindi converti il contenuto e stampa il risultato.
Verranno forniti i seguenti input:
- Riga 1: tipo di formato (
pdf,html,markdowno altro) - Riga 2: contenuto del documento da convertire
Per esempio, dato:
html
Welcome to Go ProgrammingIl tuo output dovrebbe essere:
HTML: <p>Welcome to Go Programming</p>E dato:
markdown
Chapter OneIl tuo output dovrebbe essere:
MD: # Chapter OneE dato:
pdf
Annual Report 2024Il tuo output dovrebbe essere:
PDF: Annual Report 2024E dato:
docx
Meeting NotesIl tuo output dovrebbe essere:
PDF: Meeting NotesNota che il codice principale non ha bisogno di conoscere i tipi specifici di convertitore. Chiede semplicemente alla factory un convertitore e usa l'interfaccia. In questo modo sarà facile aggiungere nuovi formati in seguito senza modificare il codice client!
Provalo tu
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Leggi il tipo di formato
scanner.Scan()
format := scanner.Text()
// Leggi il contenuto del documento
scanner.Scan()
content := scanner.Text()
// TODO: Usa la factory per creare il convertitore appropriato
// TODO: Converti il contenuto e stampa il risultato
fmt.Println(result)
}
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 di OOP in Go
File esterniWorkspace e moduli GoPacchetti e importazioniNomi esportati e non esportatiIntroduzione all’OOP in GoGli struct come classiDefinire metodi sugli structReceiver con puntatore vs receiver con valoreInizializzazione degli structFunzioni costruttriciRiepilogo - Calcolatrice semplice4Interfacce
Introduzione alle interfacceImplementazione implicitaL’interfaccia come contrattoInterfaccia vuota (any)Asserzione di tipoSwitch sul tipoComposizione di interfacceInterfacce Stringer ed ErrorRipasso - Calcolatore di forme7Incapsulamento
Campi esportati e non esportatiIncapsulamento a livello di packageMetodi Getter e SetterNascondimento delle informazioni in GoRiepilogo - Registri degli studenti10Tipi generici (Go 1.18+)
Introduzione ai tipi genericiParametri di tipoVincoli di tipoStruct genericheSoluzione alternativa per i metodi genericiRiepilogo - Collezione generica13Modelli di progettazione Parte 1
Introduzione ai modelli di progettazioneModello SingletonModello FactoryModello Abstract FactoryModello ObserverModello Strategy2Approfondimento su tipi e struct
Tipi di base e compostiDefinizioni di tipi personalizzatiTag delle structStruct anonimeStruct annidateValori zero e predefinitiRipasso - Rubrica5Composizione invece dell'ereditarietà
Perché Go non ha l'ereditarietàFondamenti dell'embedding delle structPromozione dei metodiEmbedding di più structEmbedding e aggregazione a confrontoMascheramento dei metodi embeddedRiepilogo: gerarchia dei dipendenti8Gestione degli errori e OOP
L'interfaccia errorTipi di errore personalizzatiWrapping degli errori (fmt.Errorf)Errori sentinellaerrors.Is() ed errors.As()Panic, Defer e RecoverRiepilogo - Parser di file11Libreria standard e OOP
io.Reader e io.Writersort.InterfaceInterfaccia fmt.Stringerencoding/json con le structInterfaccia http.HandlerRipasso - modelli REST API14Modelli di progettazione – Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositeMiddleware come Decorator3Puntatori e memoria
Concetti base dei puntatori in GoPuntatori a structPassaggio per valore vs per riferimentoLa funzione new()Garbage collection in GoRiepilogo - Costruttore di liste concatenate6Polimorfismo in Go
Polimorfismo tramite interfacceDuck typing in GoRegole di soddisfacimento delle interfacceCollezioni polimorficheIniezione delle dipendenzeRiepilogo - Elaboratore di pagamenti9Concorrenza e OOP
Basi delle goroutineCanali e comunicazioneCanali bufferizzati vs non bufferizzatiIstruzione selectsync.Mutex e sync.RWMutexsync.WaitGroupProgettazione di struct thread-safeRiepilogo: worker poolEsercitati da solo: Compilatore Go online