Ce este
Șablonul Abstract Factory creează familii întregi de obiecte înrudite, care merg împreună. Acolo unde o metodă-fabrică (Factory Method) creează un singur produs, o fabrică abstractă creează un set care se potrivește — și garantează că piesele nu se amestecă niciodată.
Cazul clasic este tematizarea: o temă deschisă trebuie să producă butoane deschise și etichete deschise, niciodată un amestec.
Exemplu: o fabrică de teme
renderScreen primește orice UIFactory și construiește din ea un ecran unitar. Schimbarea întregului aspect înseamnă un singur argument — iar amestecarea temelor este imposibilă prin însăși construcția codului.
O singură fabrică, o singură familie unitară
Tema deschisă produce doar piese deschise, tema închisă doar piese închise. renderScreen nu se schimbă niciodată.
Ieșire: program Go și rezultatul capturat
package main
import "fmt"
type Button interface{ Render() string }
type Label interface{ Render() string }
// Fabrica abstractă creează o întreagă familie de piese care se potrivesc.
type UIFactory interface {
NewButton() Button
NewLabel() Label
}
type LightButton struct{}
func (LightButton) Render() string { return "[ OK ] buton deschis" }
type LightLabel struct{}
func (LightLabel) Render() string { return "salut etichetă deschisă" }
type DarkButton struct{}
func (DarkButton) Render() string { return "[ OK ] buton închis" }
type DarkLabel struct{}
func (DarkLabel) Render() string { return "salut etichetă închisă" }
type LightTheme struct{}
func (LightTheme) NewButton() Button { return LightButton{} }
func (LightTheme) NewLabel() Label { return LightLabel{} }
type DarkTheme struct{}
func (DarkTheme) NewButton() Button { return DarkButton{} }
func (DarkTheme) NewLabel() Label { return DarkLabel{} }
func renderScreen(f UIFactory) {
fmt.Println(f.NewLabel().Render())
fmt.Println(f.NewButton().Render())
}
func main() {
renderScreen(LightTheme{})
renderScreen(DarkTheme{})
}
Când să îl folosești
Folosește-l atunci când mai multe obiecte trebuie să rămână consecvente între ele — teme, seturi de componente grafice specifice unei platforme, perechi potrivite de formate de import/export.
Renunță la el atunci când produsele nu trebuie să se potrivească între ele. Obiectele independente merită constructori independenți, nu o fabrică de familii.
Avantaje și dezavantaje
Avantaje: consecvența familiei este garantată; familii întregi se schimbă cu o singură valoare; codul apelant depinde doar de interfețe.
Dezavantaje: multe interfețe și tipuri pentru o treabă mică; adăugarea unui nou produs în familie înseamnă modificarea fiecărei fabrici.