Modello Abstract Factory
Fa parte della sezione Programmazione orientata agli oggetti del percorso GO di Coddy. Lezione 88 di 107.
Il pattern Abstract Factory estende il pattern Factory creando famiglie di oggetti correlati senza specificarne i tipi concreti. Invece di una singola funzione factory, definisci un'interfaccia factory che viene implementata da più factory concrete, ciascuna delle quali produce un insieme coerente di oggetti correlati.
Considera un toolkit per interfacce utente che deve creare pulsanti e caselle di controllo. I diversi sistemi operativi richiedono implementazioni diverse, ma i componenti devono funzionare insieme in modo coerente:
type Button interface {
Render() string
}
type Checkbox interface {
Check() string
}
// Interfaccia della fabbrica astratta
type GUIFactory interface {
CreateButton() Button
CreateCheckbox() Checkbox
}Ogni fabbrica concreta produce una famiglia di componenti correlati:
// Famiglia Windows
type WindowsButton struct{}
func (w WindowsButton) Render() string { return "Windows Button" }
type WindowsCheckbox struct{}
func (w WindowsCheckbox) Check() string { return "Windows Checkbox" }
type WindowsFactory struct{}
func (w WindowsFactory) CreateButton() Button { return WindowsButton{} }
func (w WindowsFactory) CreateCheckbox() Checkbox { return WindowsCheckbox{} }
// Famiglia Mac
type MacButton struct{}
func (m MacButton) Render() string { return "Mac Button" }
type MacCheckbox struct{}
func (m MacCheckbox) Check() string { return "Mac Checkbox" }
type MacFactory struct{}
func (m MacFactory) CreateButton() Button { return MacButton{} }
func (m MacFactory) CreateCheckbox() Checkbox { return MacCheckbox{} }Il codice client funziona con l’interfaccia della factory, rimanendo indipendente dalle implementazioni concrete:
func BuildUI(factory GUIFactory) {
button := factory.CreateButton()
checkbox := factory.CreateCheckbox()
fmt.Println(button.Render(), checkbox.Check())
}Usa Abstract Factory quando il tuo sistema deve funzionare con più famiglie di prodotti correlati e vuoi assicurarti che i componenti della stessa famiglia vengano utilizzati insieme. È più complesso di una semplice Factory, quindi ricorri a questo modello solo quando hai davvero bisogno di gestire famiglie di prodotti.
Sfida
FacileCostruiamo un sistema per un negozio di mobili usando il pattern Abstract Factory! Creerai factory che producono famiglie di mobili correlati: ogni factory produce uno stile coerente (Modern o Vintage), assicurando che sedie e tavoli provenienti dalla stessa factory siano esteticamente coordinati.
Organizzerai il codice in tre file:
furniture.go: definisci le interfacce dei prodotti e i tipi concreti di mobili.Crea due interfacce di prodotto:
Chaircon un metodoSitOn() stringTablecon un metodoPlaceItems() string
Implementa due famiglie di mobili:
- Famiglia Modern:
ModernChairrestituisceSitting on a sleek modern chaireModernTablerestituiscePlacing items on a glass modern table - Famiglia Vintage:
VintageChairrestituisceSitting on an ornate vintage chaireVintageTablerestituiscePlacing items on a wooden vintage table
factory.go: definisci l'interfaccia della factory astratta e le factory concrete.Crea un'interfaccia
FurnitureFactorycon due metodi:CreateChair() ChairCreateTable() Table
Implementa due factory concrete:
ModernFactoryche produceModernChaireModernTableVintageFactoryche produceVintageChaireVintageTable
Crea anche una funzione
GetFactory(style string) FurnitureFactoryche restituisce la factory appropriata in base allo stile (modernovintage). UsaModernFactorycome valore predefinito per gli stili non riconosciuti.main.go: usa le tue factory per arredare le stanze.Crea una funzione
FurnishRoom(factory FurnitureFactory) stringche usa la factory per creare una sedia e un tavolo, quindi restituisce una stringa formattata che mostra entrambe le azioni su righe separate.Leggi uno stile in input, ottieni la factory appropriata, arreda una stanza e stampa il risultato.
Verranno forniti i seguenti input:
- Riga 1: stile dei mobili (
modern,vintageo qualsiasi altro valore)
Per esempio, dato:
modernL'output dovrebbe essere:
Sitting on a sleek modern chair
Placing items on a glass modern tableE dato:
vintageL'output dovrebbe essere:
Sitting on an ornate vintage chair
Placing items on a wooden vintage tableE dato:
rusticL'output dovrebbe essere:
Sitting on a sleek modern chair
Placing items on a glass modern tableNota come la funzione FurnishRoom funzioni con qualsiasi factory tramite l'interfaccia. Non sa se sta creando mobili moderni o vintage. Questo assicura che tutti i mobili di una stanza provengano dalla stessa famiglia, mantenendo uno stile coerente!
Provalo tu
package main
import "fmt"
// FurnishRoom usa una factory per creare i mobili e restituisce il risultato
// TODO: Implementa questa funzione
// - Usa factory per creare una sedia e un tavolo
// - Restituisci una stringa con il risultato di SitOn() sulla prima riga e quello di PlaceItems() sulla seconda riga
func FurnishRoom(factory FurnitureFactory) string {
// TODO: Crea una sedia e un tavolo usando factory
// TODO: Restituisci una stringa formattata con le due azioni su righe separate
return ""
}
func main() {
var style string
fmt.Scanln(&style)
// TODO: Ottieni la factory appropriata in base a style
// TODO: Arreda una stanza usando factory
// TODO: Stampa il risultato
}
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